hdu 2196 Computer 【樹形DP求直徑】
阿新 • • 發佈:2018-12-07
題意:求每個點的最遠距離
思路:對於有向圖<u,v> dp[u][0] 表示 u向子節點(向下)能到達的最圓距離
dp[u][1] 表示 u向子節點能到達的此遠距離
dp[u][2] 表示 u向父節點(向上)能到達的最遠距離
第一次 dfs 從下到上遍歷圖求出 dp[u][0] dp[u][1],
第二次 dfs 從上到下遍歷圖求出 dp[u][2];
程式碼還有解釋
#include<stdio.h> #include<string.h> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N=5e4+10; struct node { int v,ne,w; }edge[N]; int head[N],isroot[N]; int dp[N][3]; int e,n; void add(int a,int b,int c) { edge[e].v=b; edge[e].w=c; edge[e].ne=head[a]; head[a]=e++; } void dfs1(int u) { for(int i=head[u];i!=-1;i=edge[i].ne) { int v=edge[i].v; dfs1(v); int temp=dp[v][0]+edge[i].w; if(temp>dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0]=temp; } else if(temp>dp[u][1]) dp[u][1]=temp; } } void dfs2(int u) { for(int i=head[u];i!=-1;i=edge[i].ne) { int v=edge[i].v; int w=edge[i].w; if(dp[u][0]==dp[v][0]+w) dp[v][2]=max(dp[u][2],dp[u][1])+w; //如果此時v就是u向下走的最長距離樹枝的節點, //那麼讓dp[u][2],dp[u][1]比較,因為要更新向上走的最遠距離; //向上走的最遠距離可能是u向上走的最遠距離也可能是從u到子節點的此遠距離(因為此時為u向下的最遠距離的樹枝) else dp[v][2]=max(dp[u][2],dp[u][0])+w; //否則用dp[u][2],dp[u][0]比較,更新v向上走的最遠距離 dfs2(v); } } int main() { while(~scanf("%d",&n)) { int a,b,c; memset(head,-1,sizeof(head)); memset(isroot,0,sizeof(isroot)); e=0; for(int i=2;i<=n;i++) { scanf("%d %d",&b,&c); add(b,i,c); } memset(dp,0,sizeof(dp)); dfs1(1); dfs2(1); for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][2],dp[i][0])); //最後讓向上的最遠距離和向下的最遠距離比較 } return 0; }