HDU 2196 Computer

来源:互联网 发布:量子通信网络快吗 编辑:程序博客网 时间:2024/06/01 10:17

1.题目描述:点击打开链接

2.解题思路:本题是经典的树形dp问题:求一棵树上每个结点的最远点的距离。这个问题可以用如下的方法解决:首先随意选择一个点作为根结点进行dfs,求出所有点到根结点的最远距离的那个结点,假设是p,接下来以p树根,再进行一次dfs,求出最远的点q,那么p-q就是树上的直径。并且可以证明,所有点的最远点要么是p,要么q。详细的证明可以参考如下链接,这样整个问题就可以在O(N)时间内解决。

证明链接:点击打开链接

3.代码:

#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<list>#include<complex>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef pair <int,int> P;const int N = 20000 + 10;struct Edge{int to;int dist;int next;};Edge e[N];int head[N];int d1[N], d2[N];int cnt, n;void init(){    memset(head,-1,sizeof(head));    cnt=0;}void addedge(int u, int v, int dist){e[cnt]=Edge{v,dist,head[u]};head[u] = cnt++;}void dfs(int u, int fa, int dist, int*d){d[u] = dist;for (int i = head[u]; ~i; i = e[i].next){int v = e[i].to;if (v != fa)dfs(v, u, dist+e[i].dist, d);}}int main(){while (~scanf("%d", &n)){    init();int v, dist;for (int i = 2; i<=n; i++){scanf("%d%d", &v, &dist);addedge(i, v, dist);addedge(v, i, dist);}dfs(1, 0, 0, d1);int p=1, q=1; //p是直径的一端int mx = 0;for (int i = 1; i <= n; i++)if (mx<d1[i]){mx = d1[i]; p = i;}dfs(p, 0, 0, d1);mx = 0;for (int i = 1; i <= n; i++)if (mx<d1[i]){mx = d1[i]; q = i; //q是直径的另一端}dfs(q, 0, 0, d2);for (int i = 1; i <= n; i++)printf("%d\n",max(d1[i],d2[i]));}}


0 0