ZOJ 3527
这题难在破环。
对于不是环的情况,只需按照一般的树形DP来做,一步一步往根递推就可以了。对于环,则枚举其中一点的两种情况,取或不取,然后再递推,就可以了。当到达某结点的下一结点为环开始的点时,退出即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int MAX=210010; 7 8 int fr[MAX],next[MAX],ch[MAX]; 9 int N,qt[MAX],top,in[MAX]; 10 long long dp[MAX][2],dp1[MAX][2]; 11 bool flag[MAX]; 12 13 long long maxt(long long a,long long b){ 14 if(a>b)return a; 15 return b; 16 } 17 18 long long dfs(int f,int u,long long d[][2], bool choice){ 19 while(true){ 20 int v=next[u]; 21 if(choice) flag[v]=flag[u]=true; 22 if(v==f) break; 23 d[v][0]+=maxt(d[u][0],d[u][1]); 24 d[v][1]+=maxt(d[u][0],d[u][1]+ch[u]); 25 u=v; 26 } 27 if(choice){ 28 return maxt(d[u][0],d[u][1]+ch[u]); 29 } 30 else{ 31 return maxt(d[u][0],d[u][1]); 32 } 33 } 34 35 long long sech(int f){ 36 int u=next[f]; 37 dp1[u][0]+=dp[f][0]; 38 dp1[u][1]+=dp[f][0]; 39 long long res1=dfs(f,u,dp1,false); 40 dp[u][0]+=dp[f][1]; 41 dp[u][1]+=(dp[f][1]+ch[f]); 42 long long res2=dfs(f,u,dp,true); 43 return maxt(res1,res2); 44 } 45 46 int main(){ 47 while(scanf("%d",&N)!=EOF){ 48 top=0; 49 memset(in,0,sizeof(in)); 50 memset(flag,false,sizeof(flag)); 51 for(int i=1;i<=N;i++){ 52 scanf("%d%d%d",&fr[i],&ch[i],&next[i]); 53 in[next[i]]++; 54 dp[i][0]=0;dp[i][1]=fr[i]; 55 } 56 for(int i=1;i<=N;i++) 57 if(in[i]==0) 58 qt[++top]=i; 59 while(top!=0){ 60 int u=qt[top--]; 61 int v=next[u]; 62 flag[u]=true; 63 dp[v][1]+=maxt(dp[u][0],dp[u][1]+ch[u]); 64 dp[v][0]+=maxt(dp[u][0],dp[u][1]); 65 in[v]--; 66 if(in[v]==0) 67 qt[++top]=v; 68 } 69 long long sumt=0; 70 memcpy(dp1,dp,sizeof(dp)); 71 for(int i=1;i<=N;i++){ 72 if(!flag[i]){ 73 sumt+=sech(i); 74 } 75 } 76 printf("%lld\n",sumt); 77 } 78 return 0; 79 }