AcWing 1072. 树的最长路径
考察:树形dp
思路:
从定义出发我们需要枚举所有路径,但直接枚举两个点直接的路径会超时,所以要分类集合枚举.已知树的路径一定会经过某个点,那么我们以点来分类集合.以路径的最高点来分类,经过这个点的最长路径 = 经过此点最长边+经过此点次长边.因此状态转移方程 f[u] = f[v1] +f[v2]+len(u,v1)+len(u,v2).
我们以哪个点开始dfs,相当于把此点当根
注意:因为是无向的,所以要建立两个方向的边
关于求次大值以d>最大值与小于最大值分类
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int N = 10010; 7 struct Road{ 8 int to,ne,w,fr; 9 }road[N<<1]; 10 int h[N],idx,ans,f[N]; 11 void add(int a,int b,int c) 12 { 13 road[idx].w = c,road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++; 14 } 15 int dfs(int u,int fa)//返回u结点往下的最大长度 16 { 17 int dist = 0,d1 = 0,d2 = 0; 18 for(int i=h[u];i!=-1;i=road[i].ne) 19 { 20 int v = road[i].to; 21 if(v==fa) continue; 22 int d = dfs(v,u)+road[i].w; 23 dist = max(d,dist); 24 if(d>=d1) d2 = d1,d1 = dist;//dist是最大值,不能用dist与d1比较 25 else if(d>d2) d2 = d; 26 } 27 f[u] = d1+d2; 28 return dist; 29 } 30 int main() 31 { 32 int n,root = 1; 33 scanf("%d",&n); 34 memset(h,-1,sizeof h); 35 for(int i=1;i<n;i++) 36 { 37 int a,b,c; 38 scanf("%d%d%d",&a,&b,&c); 39 add(a,b,c); add(b,a,c); 40 } 41 dfs(root,-1); 42 for(int i=1;i<=n;i++) ans = max(ans,f[i]); 43 printf("%d\n",ans); 44 return 0; 45 }