【noip2007】树网的核

题解:

首先我们要知道一个性质:如果有多条直径 这个核不论在哪条直径上 答案都是一样的

这样我们就可以随便找一条直径 在这条直径上枚举核的位置

并且dfs预处理maxlon[i] (i在直径上) 表示到i的路径不经过直径的 离i最远的点到i的距离

这时核的偏心距就是max(maxlon[i],核的端点到直径的端点的长度) (i为核上的点)

这样就能O(n)求解

 

代码:

 1 #include <cstdio>
 2 const int N=301,M=1001;
 3 struct inli{
 4     int next,data,lon;
 5     inli(const int a=0,const int b=0,const int c=0):
 6         next(a),data(b),lon(c){}
 7 }line[N*2];
 8 int S,n,m,son[N],fat[N],dis[N],bo[N],maxlon[N],seclon[N],hard[N],nl;
 9 int max(int x,int y){ return x>y ? x : y;}
10 int min(int x,int y){ return x<y ? x : y;}
11 void makedis(int t){
12     bo[t]=1;
13     for (int i=son[t];i;i=line[i].next)
14     if (!bo[line[i].data]){
15         int ne=line[i].data;
16         dis[ne]=dis[t]+line[i].lon;
17         makedis(ne);
18     }
19 }
20 void makefat(int t){
21     for (int i=son[t];i;i=line[i].next)
22     if (line[i].data!=fat[t]){
23         int ne=line[i].data;
24         fat[ne]=t;
25         makefat(ne);
26         if (maxlon[ne]+line[i].lon>maxlon[t]){
27             seclon[t]=maxlon[t];
28             maxlon[t]=maxlon[ne]+line[i].lon;
29             hard[t]=i;
30         }
31     }
32 }
33 int makef(int x,int y){
34     if (!x) return 0;
35     int i=hard[x];
36     if (y<line[i].lon) return maxlon[x];
37     return max(seclon[x],makef(line[i].data,y-line[i].lon));
38 }
39 int getans(){
40     int res=100000000;
41     for (int i=S,x=seclon[S];i;x+=line[hard[i]].lon,i=line[hard[i]].data){
42         if (x>res) break;
43         res=min(res,max(makef(i,m),x));
44     }
45     return res;
46 }
47 int main(){
48     scanf("%d%d",&n,&m);
49     for (int x,y,z,i=1;i<n;i++){
50         scanf("%d%d%d",&x,&y,&z);
51         line[++nl]=inli(son[x],y,z),son[x]=nl;
52         line[++nl]=inli(son[y],x,z),son[y]=nl;
53     }
54     makedis(1);
55     int x=0;
56     for (int i=1;i<=n;i++)
57     if (dis[i]>x) x=dis[i],S=i;
58     makefat(S);
59     printf("%d",getans());
60 }
View Code

 

posted @ 2013-10-24 00:13  g_word  阅读(231)  评论(0编辑  收藏  举报