【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 }