本文出自 http://blog.csdn.net/shuangde800
題目傳送門
題意:
給出一棵樹,求離每個節點最遠的點的距離
思路:
把無根樹轉化成有根樹分析,
對於上面那棵樹,要求距結點2的最長距離,那麼,就需要知道以2為頂點的子樹(藍色圈起的部分,我們叫它Tree(2)),距頂點2的最遠距離L1
還有知道2的父節點1為根節點的樹Tree(1)-Tree(2)部分(即紅色圈起部分),距離結點1的最長距離+dist(1,2) = L2,那麼最終距離結點2最遠的距離就是max{L1,L2}
f[i][0],表示頂點為i的子樹的,距頂點i的最長距離
f[i][1],表示Tree(i的父節點)-Tree(i)的最長距離+i跟i的父節點距離
要求所有的f[i][0]很簡單,只要先做一次dfs求每個結點到葉子結點的最長距離即可。
然後要求f[i][1], 可以從父節點遞推到子節點,
假設節點u有n個子節點,分別是v1,v2...vn
那麼
如果vi不是u最長距離經過的節點,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])
如果vi是u最長距離經過的節點,那麼不能選擇f[u][0],因為這儲存的就是最長距離,要選擇Tree(u)第二大距離secondDist,
可得f[vi][1] = dist(vi, u) + max(secondDist, f[u][1])
代碼:
/**========================================== * This is a solution for ACM/ICPC problem * * @author: shuangde * @blog: blog.csdn.net/shuangde800 * @email: zengshuangde@gmail.com *===========================================*/#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<cmath>#include<cstring>using namespace std;typedef long long int64;const int INF = 0x3f3f3f3f;const double PI = acos(-1.0);const int MAXN = 10010;struct Node{ int v, w;};vector<Node>adj[MAXN];int indeg[MAXN];int val[MAXN];int n, m;int64 f[MAXN][2];int vis[MAXN];int64 dfs1(int u){ vis[u] = true; f[u][0] = 0; for(int i=0; i<adj[u].size(); ++i){ int v = adj[u][i].v; int w = adj[u][i].w; if(vis[v]) continue; f[u][0] = max(f[u][0], dfs1(v)+w); } return f[u][0];}void dfs2(int u, int fa_w){ vis[u] = true; int max1=0, v1, max2=0, v2; for(int i=0; i<adj[u].size(); ++i){ int v = adj[u][i].v; int w = adj[u][i].w; if(vis[v]) continue; int tmp = f[v][0] + w; if(tmp > max1){ max2 = max1; v2 = v1; max1 = tmp; v1 = v; }else if(tmp == max1 || tmp>max2){ max2 = tmp; v2 = v; } } if(u != 1){ int tmp = f[u][1]; int v = -1; if(tmp > max1){ max2 = max1; v2 = v1; max1 = tmp; v1 = v; }else if(tmp == max1 || tmp>max2){ max2 = tmp; v2 = v; } } for(int i=0; i<adj[u].size(); ++i){ int v = adj[u][i].v; int w = adj[u][i].w; if(vis[v]) continue; if(v==v1){ f[v][1] = max2 + w; }else{ f[v][1] = max1 + w; } dfs2(v, w); }}int main(){ while(~scanf("%d", &n) && n){ for(int i=1; i<=n; ++i) adj[i].clear(); for(int u=2; u<=n; ++u){ int v, w; scanf("%d%d", &v, &w); adj[u].push_back((Node){v, w}); adj[v].push_back((Node){u, w}); } memset(f, 0, sizeof(f)); memset(vis, 0, sizeof(vis)); dfs1(1); memset(vis, 0, sizeof(vis)); dfs2(1, 0); for(int i=1; i<=n; ++i){ cout << max(f[i][0], f[i][1]) << endl; } } return 0;}