HDU 2196 Computer 经典树形DP
一开始看错题了,后来发现原来是在一颗带权的树上面求出距离每一个点的最长距离,做两次dfs就好,具体的看注释?
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <queue> #include <stack> using namespace std; typedef long long LL; const int maxn = 10000 + 5; int ch[maxn],nxt[maxn],v[maxn],w[maxn]; int mdep[maxn],sdep[maxn],f[maxn],mfrom[maxn]; int ecnt,n; inline void addedge(int uu,int vv,int ww) { v[ecnt] = vv; w[ecnt] = ww; nxt[ecnt] = ch[uu]; ch[uu] = ecnt++; } //dfs求解从子节点过来的最大值和次大值 int dfs(int now) { mdep[now] = sdep[now] = 0; if(ch[now] == -1) return 0; for(int i = ch[now];~i;i = nxt[i]) { int ret = dfs(v[i]) + w[i]; if(ret > mdep[now]) { sdep[now] = mdep[now]; mdep[now] = ret; mfrom[now] = v[i]; } else if(ret > sdep[now]) sdep[now] = ret; } return mdep[now]; } //dfs1求出答案 void dfs1(int now) { //如果当前节点是叶子节点,最大值必定是从父亲节点更新过来的 if(ch[now] == -1) return; //否则往下更新 for(int i = ch[now];~i;i = nxt[i]) { if(mfrom[now] == v[i]) { //如果当前儿子这边有最大深度 f[v[i]] = max(f[now],sdep[now]) + w[i]; } else f[v[i]] = max(f[now],mdep[now]) + w[i]; dfs1(v[i]); } //最大距离来自儿子 f[now] = max(f[now],mdep[now]); } int main() { while(scanf("%d",&n) != EOF) { memset(ch,-1,sizeof(ch)); memset(f,0,sizeof(f)); memset(mfrom,-1,sizeof(mfrom)); ecnt = 0; for(int i = 2;i <= n;i++) { int a,b; scanf("%d%d",&a,&b); addedge(a,i,b); } dfs(1); dfs1(1); for(int i = 1;i <= n;i++) printf("%d\n",f[i]); } return 0; }