【POJ1985】Cow Marathon
树的直径的模板题
我们存图以后,对这张图(树)进行一次dfs,定义sum1表示从当前节点向他的儿子走的最长路径是多少,sum2表示次长路径是多少。我们每次先用当前路径的长度+当前路径前往的节点的sum1更新当前节点的sum2,如果更新后sum2大于sum1,那么我们交换他们的数值,不难发现这样是正确的,计算完成后我们向当前节点的父亲返回他的sum1,这样之后答案ans就是max(sum1+sum2),这个算法将每一个点遍历一遍,因此,时间复杂度为O(n)。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 int n,m; 8 struct edge { 9 int next,to,dis; 10 }a[100010<<1]; 11 int num,head[100010<<1]; 12 int f[100010],ans; 13 void add(int from,int to,int dis) { 14 a[++num].next=head[from]; 15 a[num].to=to; 16 a[num].dis=dis; 17 head[from]=num; 18 } 19 int dfs(int u,int fa) { 20 int sum1=0,sum2=0; 21 for(int i=head[u];i;i=a[i].next) 22 if(a[i].to!=fa) { 23 sum2=max(sum2,dfs(a[i].to,u)+a[i].dis); 24 if(sum2>sum1) swap(sum1,sum2); 25 ans=max(ans,sum1+sum2); 26 } 27 return sum1; 28 } 29 int main() { 30 scanf("%d%d",&n,&m); 31 for(int i=1;i<=m;i++) { 32 char c; 33 int x,y,z; 34 cin>>x>>y>>z>>c; 35 add(x,y,z); 36 add(y,x,z); 37 } 38 dfs(1,0); 39 printf("%d\n",ans); 40 return 0; 41 }