標籤:io os ar for sp c on amp r
題意:求節點間的最大距離
先DFS一次 記錄下 每一節點的子樹下的最大距離(DP[ u ] [ 0 ])和第二大距離(DP[ u ] [ 1 ])
用DP[ v ] [ 2 ] 表示由v的父節點來的最大距離
再取DP[ u ] [ 0 ] 與 DP[ u ][ 2 ] 的最值
#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <iostream>#include <algorithm>#include <sstream>#include <cmath>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include <set>#include <map>#include <time.h>;#define cler(arr, val) memset(arr, val, sizeof(arr))#define FOR(i,a,b) for(int i=a;i<=b;i++)#define IN freopen ("in.txt" , "r" , stdin);#define OUT freopen ("out.txt" , "w" , stdout);typedef long long LL;const int MAXN = 10014;const int MAXM = 20014;const int INF = 0x3f3f3f3f;const int mod = 1000000007;struct node{ int v,next; LL val;} edge[MAXM];int head[MAXM],tol;LL dp[MAXN][3];bool vis[MAXN];void init(){ cler(head,-1); tol=0;}void addedge(int u,int v,LL val){ edge[tol].v=v,edge[tol].val=val,edge[tol].next=head[u]; head[u]=tol++; edge[tol].v=u,edge[tol].val=val,edge[tol].next=head[v]; head[v]=tol++;}void dfs1(int u){ if(vis[u]) return ; vis[u]=true; for(int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { dfs1(v); dp[u][1]=max(dp[u][1],dp[v][0]+edge[i].val); if(dp[u][1]>dp[u][0])swap(dp[u][1],dp[u][0]); } }}void dfs2(int u){ if(vis[u]) return ; vis[u]=true; for(int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].v,val=edge[i].val; if(!vis[v]) { if(dp[u][0]>dp[v][0]+val)//dp[u][0]不是由dp[v][0]+val而來的 dp[v][2]=max(dp[v][2],max(dp[u][0]+val,dp[u][2]+val));//所以從非v子樹來的更長 else //dp[u][0]由dp[v][0]+val而來的 dp[v][2]=max(dp[v][2],max(dp[u][1]+val,dp[u][2]+val));//判斷非v子樹來的哪個長 dfs2(v); } }}int main(){#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin);#endif int n; while(~scanf("%d",&n)) { init(); for(int i=2; i<=n; i++) { int a; LL b; scanf("%d %I64d",&a ,&b ); addedge(i,a,b); } cler(vis,false); cler(dp,0); dfs1(1); cler(vis,false); dfs2(1); for(int i=1;i<=n;i++) printf("%I64d\n",max(dp[i][2],dp[i][0])); }}
【樹形DP】 HDU 2196 Computer