标签:
5 1 1 2 1 3 1 1 1
3 2 3 4 4
若想做这道题 首先要懂得树的最长路怎么计算
首先假设树的最长路的两个叶子节点为v1,v2,那么现有结论,从任意一点u出发走到的最远的点一定是(v1,v2)中的一点,然后
再从v1或者v2出发走到的最远点一定是v2或者v1。所以经过两次搜索就能找到最长路径。
这里有证明:
假设 s-t这条路径为树的直径,或者称为树上的最长路
现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路
证明:
1 设u为s-t路径上的一点,结论显然成立,否则设搜到的最远点为T则
dis(u,T) >dis(u,s) 且 dis(u,T)>dis(u,t) 则最长路不是s-t了,与假设矛盾
2 设u不为s-t路径上的点
首先明确,假如u走到了s-t路径上的一点,那么接下来的路径肯定都在s-t上了,而且终点为s或t,在1中已经证明过了
所以现在又有两种情况了:
1:u走到了s-t路径上的某点,假设为X,最后肯定走到某个端点,假设是t ,则路径总长度为dis(u,X)+dis(X,t)
2:u走到最远点的路径u-T与s-t无交点,则dis(u-T) >dis(u,X)+dis(X,t);显然,如果这个式子成立,
则dis(u,T)+dis(s,X)+dis(u,X)>dis(s,X)+dis(X,t)=dis(s,t)最长路不是s-t矛盾
证明转自 :http://www.cnblogs.com/wuyiqi/archive/2012/04/08/2437424.html而这道题不是找最长路径,是找某个节点x所能到达的最长路径。首先这个节点x的最长路径要么是到v1的路径,要么就是到v2的路径。由于我们不知道从那边走才是最长的路径 所以需要分别从v1,v2点再次搜索 共需要三次搜索 在这里可能一些同学会说了两次搜索不行吗?我们在第一次搜索找到了v1,v2中的一个点 然后再从v1或者v2点搜索到另外一个点v2或者v1 搜索的过程中用dist[x]保存走过的路径长度 最后输出的时候通过比较当前的路径和最长路径减去到当前的路径 取最大值(max(dist[v]-dist[x],dist[x])) 其实我也是这一些同学的一份子 提交的时候Wa了 后来仔细分析了一下 这样是错误的 我们只能保证x走到的最远点有一点是v1,或者v2 却不能保证另外一点也是 所以不能这样减去。看看这个图
可以看到最长路径为7-》1-》4-》5-》6-》8 dist[7]=dist[8]=5
第一次从1搜索后得到dist[8]=5,dist[2]=3
如果根据这个公式(max(dist[8]-dist[2],dist[2]))=3 可是在图中我们可以明显看到dist[2]的最大值为2-》5-》4-》1-》7 长度为4
就说这么多吧 附上代码:
#include <stdio.h> #include <vector> #include <algorithm> #include <string.h> using namespace std; int root,max_len; int dist[10000+5]; struct Edge { int pos; int cost; Edge(int a,int x) { pos=a; cost=x; } }; vector<Edge>tree[10000+5]; void dfs(int u,int v,int len) { if(max_len<len) max_len=len,root=u; for(int i=0;i<tree[u].size();i++) { int pos=tree[u][i].pos; int cost=tree[u][i].cost; if(v==pos) continue; dfs(pos,u,len+cost); dist[pos]=max(dist[pos],len+cost); } } int main() { int n; while(~scanf("%d",&n)) { int max_val=0; memset(tree,0,sizeof(tree)); memset(dist,0,sizeof(dist)); for(int i=2;i<=n;i++) { int a,x; scanf("%d %d",&a,&x); tree[i].push_back(Edge(a,x)); tree[a].push_back(Edge(i,x)); } max_len=0; dfs(1,-1,0); dfs(root,-1,0); dfs(root,-1,0); for(int i=1;i<=n;i++) printf("%d\n",dist[i]); } return 0; }
hdu2196 Computer(树的直径||树中的最长路径)
标签:
原文地址:http://blog.csdn.net/su20145104009/article/details/51297098