Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 1 Accepted Submission(s) : 1
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
Input
Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.
Output
For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).
Sample Input
5 1 1 2 1 3 1 1 1
Sample Output
3 2 3 4 4
Author
scnu
首先按所给信息建图,建立的是有向图。然后将1视为根节点第一遍dfs从叶往根递推,求出每个点所能到达的最远距离和次远距离,只有当这一个点有多条分支时才存在次远距离(注意这里是有方向);
该点所能到达的最远距离可能是第一遍dfs搜到最远距离,也有可能由父亲节点+父亲节点与该节点的距离所得。所以第二遍dfs从根节点1出发往树叶边遍历。
downf[i]表示以节点 i 向其 子树搜索 所能到达的最远距离
downs[i]表示次远距离
vis[i]记录 到达最远距离的那条边(最远 和次远 不会重边)
dp[i]表示 节点i 经其父亲节点延伸(延伸到父亲的最长或着次长),所能到达的最远距离
求 i的最远时, i可能在父亲的最长路径上,也可能不再,所以要记录
最远 可能是向上最远 也可能向下 所以最后要 max(downf[k],dp[k]);
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int N=10010; struct node{ int to,cap; }a; vector<node> vt[N]; int n,dp[N],downf[N],downs[N],vis[N]; void DFS1(int u){ int flag1=-1,flag2=-1; if(downf[u]) return ; int len=vt[u].size(); if(len==0) return ; int MAX=-1; for(int i=0;i<len;i++){ //求最长距离, 由下往上递推 int v=vt[u][i].to; DFS1(v); //先dfs if(MAX<downf[v]+vt[u][i].cap){ //后处理 MAX=downf[v]+vt[u][i].cap; flag1=i; } } vis[u]=flag1; downf[u]=MAX; MAX=-1; for(int i=0;i<len;i++){ //求次长距离 int v=vt[u][i].to; if(i!=flag1 && MAX<downf[v]+vt[u][i].cap){ //i!=flag1 保证最远距离和次远距离不会重边 MAX=downf[v]+vt[u][i].cap; flag2=i; } } if(flag2!=-1) downs[u]=MAX; } void DFS2(int u){ //由上往下推 int len=vt[u].size(); if(len==0) return ; for(int i=0;i<len;i++){ int v=vt[u][i].to; if(i==vis[u]) //先处理 dp[v]=max(downs[u],dp[u])+vt[u][i].cap; //在父亲的最长路径上 else dp[v]=max(downf[u],dp[u])+vt[u][i].cap; //不在父亲的最长路径上 DFS2(v); //后dfs } } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=0;i<=n;i++) vt[i].clear(); int u; for(int v=2;v<=n;v++){ scanf("%d%d",&u,&a.cap); a.to=v; vt[u].push_back(a); } memset(dp,0,sizeof(dp)); memset(downf,0,sizeof(downf)); memset(downs,0,sizeof(downs)); DFS1(1); DFS2(1); for(int i=1;i<=n;i++) printf("%d\n",max(downf[i],dp[i])); } return 0; }
另一种建图:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int VM=10010; struct Edge{ int to,nxt; int cap; }edge[VM<<1]; int n,cnt,head[VM]; int dp[VM],downf[VM],downs[VM],vis[VM]; void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } void DFS1(int u){ int flag1=-1,flag2=-1; if(downf[u]) return ; if(head[u]==-1) return ; int MAX=-1; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; DFS1(v); if(MAX<downf[v]+edge[i].cap){ MAX=downf[v]+edge[i].cap; flag1=i; } } vis[u]=flag1; downf[u]=MAX; MAX=-1; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(i!=flag1 && MAX<downf[v]+edge[i].cap){ MAX=downf[v]+edge[i].cap; flag2=i; } } if(flag2!=-1) downs[u]=MAX; } void DFS2(int u){ if(head[u]==-1) return ; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(i==vis[u]) dp[v]=max(downs[u],dp[u])+edge[i].cap; else dp[v]=max(downf[u],dp[u])+edge[i].cap; DFS2(v); } } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n)){ cnt=0; memset(head,-1,sizeof(head)); int u,w; for(int v=2;v<=n;v++){ scanf("%d%d",&u,&w); addedge(u,v,w); } memset(dp,0,sizeof(dp)); memset(downf,0,sizeof(downf)); memset(downs,0,sizeof(downs)); DFS1(1); DFS2(1); for(int i=1;i<=n;i++) printf("%d\n",max(downf[i],dp[i])); } return 0; }