题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2196
题目意思:
给你一个无向图,但是没有环,因为有N个点,只有N-1条边
要你求出N个点在这个图上能够走的最远距离
解题思路:
这是赤裸裸的无环的无向图,我们可以把它转化为一棵树
其实以任意一个节点作为树根都是可以的,做N遍DFS就可以
但是会超时,所以我们要想办法解决超时的问题,也就是减少DFS的次数
我们可以先做一遍DFS,求出每个节点到自己子树上的最远距离,这个可以通过类似回溯的方法,但是我们保存在数组中了
然后再第二次DFS的时候,我们根据之前的DFS可以求出每个节点的父节点不经过自己的最远距离
然后将这些一起比较就可以求出来每个节点所能走的最远距离
下面上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
struct node
{
int v;
int len;
};
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
int dp[maxn];
int n;
vector<node> computer[maxn];
void read_init()
{
for(int i=0;i<=n;i++)
computer[i].clear();
for(int i=1;i<=n;i++)
dp[i] = 0;
int a,b;
node tmp;
for(int i=2;i<=n;i++)
{
scanf("%d%d",&a,&b);
tmp.v=a;
tmp.len=b;
computer[i].push_back(tmp);
tmp.v=i;
tmp.len=b;
computer[a].push_back(tmp);
}
}
void dfs_to_son(int root,int fa)
{
for(int i=0;i<computer[root].size();i++)
{
int v = computer[root][i].v;
if(v==fa)
continue;
dfs_to_son(v,root);
dp[root] = max(dp[root],computer[root][i].len+dp[v]);
computer[root][i].len = computer[root][i].len+dp[v];
}
}
void dfs_find_longest_path(int root,int fa)
{
int not_son_longest=0;
for(int i=0;i<computer[fa].size();i++)
{
int v = computer[fa][i].v;
if(v==root)
continue;
not_son_longest = max(not_son_longest,computer[fa][i].len);
}
for(int i=0;i<computer[root].size();i++)
{
int v = computer[root][i].v;
if(v==fa)
{
computer[root][i].len = not_son_longest+computer[root][i].len;
break;
}
}
for(int i=0;i<computer[root].size();i++)
{
dp[root] = max(dp[root],computer[root][i].len);
}
for(int i=0;i<computer[root].size();i++)
{
int v = computer[root][i].v;
if(v==fa)
continue;
dfs_find_longest_path(v,root);
}
}
int main()
{
while(~scanf("%d",&n))
{
read_init();
dfs_to_son(1,0);
dfs_find_longest_path(1,0);
for(int i=1;i<=n;i++)
printf("%d\n",dp[i]);
}
return 0;
}