51 12 13 11 1Sample Output32344题目的大意是,给你一棵树,求每个节点的最远的距离。我们把最开始的点作为根节点(电脑1),建立有根树。先用深搜遍历一遍树,求出对于每个父节点,其最远的子叶子节点的最远距离(下文简称为最远子距离maxs[i])和不同路径的其他子叶子节点的次远距离。如上图,1的最远子叶子节点的距离是1-2-5-6 ,是5。不同路径上的次远子距离(下文简称为次远子距离sec[i])是1-3,是3。而不是1-2-4 ,因为节点2有重复。深搜最远距离和次远距离的同时,记录好最远距离的直接子节点编号。第二遍深搜,我们进行DP,求出答案。思路如下:每次进行dp时,以当前搜索到的点为界,将这棵树分为两部分,如下图:以6号点为例,节点6的最远距离,要么是节点6最远子距离(6-9)maxs[6],要么是红圈部分的树上节点3的最远距离加上节点3到节点6的距离(5-2-1-3-6)+dist(3,6)(下文简称这个距离为局部最远距离dp[i])因此我们需要求得所有节点的局部最远距离dp[i]。局部最远距离dp[i],可以由父节点的局部最远距离推导。设父节点为par,子节点为son。①如果son不是par的最远子距离上的点,例如上图的4和3。3的最远子距离maxs[3] = 6(3-6-9),节点4不在上面dp[son] = dist(par, son)+ max(maxs[par], dp[par])②如果son是par的最远子距离上的点,例如上图的6和3。3的最远子距离maxs[3] = 6(3-6-9),节点6在上面dp[son] = dist(par, son)+ max(sec[par], dp[par])而最后的答案,就是max(dp[i], maxs[i])AC代码:#include<cstdio>#include<cstdlib>#include <algorithm>#include<cmath>using namespace std;struct node{ int dp;//局部最远距离 int ans;//最后答案 int maxs;//最远子距离 int sec;//次远子距离 int len;//该节点到父节点的距离dist(son,par) int son;//孩子 int maxson;//最远子距离的直接孩子 int bro;//兄弟} tree[10010];void dfs(int root)//深搜最远子距离和次远子距离{ if(tree[root].son==0) return; else { int p; p=tree[root].son; dfs(p); if(tree[root].maxs<tree[p].len+tree[p].maxs) { tree[root].sec = tree[root].maxs; tree[root].maxs = tree[p].len+tree[p].maxs; tree[root].maxson = p; } else if(tree[root].sec<tree[p].len+tree[p].maxs) { tree[root].sec = tree[p].len+tree[p].maxs; } //printf("!root=%d maxs=%d maxson=%d sec=%d/n",root,tree[root].maxs,tree[root].maxson,tree[root].sec); while(tree[p].bro!=0) { int tmp=p; p=tree[p].bro; dfs(p); if(tree[root].maxs<tree[p].len+tree[p].maxs) { tree[root].sec = tree[root].maxs; tree[root].maxs = tree[p].len+tree[p].maxs; tree[root].maxson = p; } else if(tree[root].sec<tree[p].len+tree[p].maxs) { tree[root].sec = tree[p].len+tree[p].maxs; } //printf("root=%d maxs=%d maxson=%d sec=%d/n",root,tree[root].maxs,tree[root].maxson,tree[root].sec); } } return;}void dfsAns(int son,int par)//深搜+DP{ if(son==1) { tree[son].dp = 0; tree[son].ans = tree[son].maxs; } else { int maxlen = tree[par].maxs; if(tree[par].maxson==son) { maxlen = tree[par].sec; } maxlen = max(tree[par].dp,maxlen); tree[son].dp = maxlen + tree[son].len; tree[son].ans = max(tree[son].dp,tree[son].maxs); } if(tree[son].son==0) return ; else dfsAns(tree[son].son,son); int p = tree[son].son; while(tree[p].bro!=0) { p = tree[p].bro; dfsAns(p,son); }}int main(){ int n; int f,l; while(~scanf("%d",&n)) { for(int i=1; i<=n; i++) { tree[i].dp=0; tree[i].ans=0; tree[i].maxs=0; tree[i].sec=0; tree[i].son=0; tree[i].maxson=0; tree[i].bro=0; } int p; for(int i=2; i<=n; i++)//左孩子右兄弟建树 { scanf("%d%d",&f,&l); if(tree[f].son==0) tree[f].son=i; else { p=tree[f].son; while(tree[p].bro!=0) { p=tree[p].bro; } tree[p].bro=i; } tree[i].len=l; } dfs(1); dfsAns(1,0); for(int i=1; i<=n; i++) { printf("%d/n",tree[i].ans); } } return 0;}/*//题解中的例子的数据91 11 23 32 23 43 16 26 3*/
新闻热点
疑难解答