【bzoj3124】[Sdoi2013]直径

1.求树的直径:

   先随便取一个点,一遍dfs找到离它最远的点l1,再以l1为起点做一遍dfs,找到离l1最远的点l2
   那么l1到l2的距离即为直径
   
2. 求出有多少条边在这棵树的所有直径上:
   两个结论:
   1)这些边一定在同一条直径上
   2)它们一定是连续的 
   因此,只需要处理第一问求出的直径,从l2到l1求出每个点不经过这条直径所能到达的最远距离,若这个距离==它到l1/l2的距离,则这个点到l1/l2所经过的边都不在答案中,答案边的范围被缩小 

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8  
  9 typedef long long LL;
 10  
 11 #define IN inline
 12 #define RG register
 13  
 14 #define N 400010
 15  
 16 struct edge
 17 {
 18     int to,next;
 19     LL w;
 20 }e[N<<1];
 21 int head[N];
 22 int cnt;
 23  
 24 LL d[N],c[N],f[N],no[N];
 25  
 26 int u,v;
 27 LL w;
 28  
 29 int n;
 30  
 31 int ans;
 32  
 33 LL dis;
 34  
 35 bool flag;
 36  
 37 IN int getint()
 38 {
 39     int x=0,f=1;char ch=getchar();
 40     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
 41     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 42     return x*f;
 43 }
 44  
 45 IN int getLL()
 46 {
 47     LL x=0,f=1;char ch=getchar();
 48     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
 49     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 50     return x*f;
 51 }
 52  
 53 IN void link(int x,int y,LL z)
 54 {
 55     e[++cnt]=(edge){y,head[x],z};
 56     head[x]=cnt;
 57 }
 58  
 59 IN void dfs(int x,int fa,int & b)
 60 {
 61     f[x]=fa;
 62     if (dis<d[x]) 
 63     { 
 64         dis=d[x]; 
 65         b=x; 
 66     } 
 67     for (RG int i=head[x];i;i=e[i].next)
 68     {
 69         int t=e[i].to;
 70         if (t!=fa)
 71         {
 72             d[t]=d[x]+e[i].w;
 73             dfs(t,x,b);
 74         }
 75     }
 76 }
 77  
 78 IN void work(int x,int fa)
 79 {
 80     if (dis<d[x]) 
 81         dis=d[x]; 
 82     for (RG int i=head[x];i;i=e[i].next)
 83     {
 84         int t=e[i].to;
 85         if (t!=fa && !no[t])
 86         {
 87             d[t]=d[x]+e[i].w;
 88             work(t,x);
 89         }
 90     }
 91 }
 92  
 93 int main()
 94 {
 95     int l1,l2;
 96     n=getint();
 97     for (RG int i=1;i<n;i++)
 98     {
 99         u=getint();v=getint();w=getLL();
100         link(u,v,w);
101         link(v,u,w);
102     }
103     dfs(1,0,l1);
104     dis=d[l1]=0;
105     dfs(l1,0,l2);
106     printf("%lld\n",dis);
107     int l=l1,r=l2;
108     for (RG int i=l2;i!=0;i=f[i])
109         no[i]=1; 
110     for (RG int i=f[l2];i!=l1;i=f[i])
111     {
112         int r1=d[i],r2=d[l2]-d[i];
113         dis=d[i]=0;
114         work(i,0);
115         if (dis==r1 && !flag)
116             l=i,flag=true;
117         if (dis==r2)
118             r=i;
119     }
120     for (RG int i=r;i!=l;i=f[i])
121         ans++;
122     printf("%d",ans);
123     return 0;
124 }

 

posted @ 2016-04-13 14:58  Yangjiyuan  阅读(316)  评论(0编辑  收藏  举报