树形DP zoj 3527



题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3527

/*以前做过一道类似的题目,但是这次看到 因为的失误没有看到一句话 把这题直接看成网络流,交给队友处理,看了解题报告才发现这题和我以前做过的一道题神似。

在这个时刻请准许我吐槽一下。。。法克油。。

好了 讲下这题的思路:

首先,每个城市只有一个相关的城市。那么我们必然可以得知每个城市的父节点只有一个。

我们可以不去理会 边的方向。

从而我们可以得知,这个图是由M个子图构成,并且每个子图都是由一个环带着一些树枝。我们可以先对树枝进行树状DP。然后对环上的节点进行DP:任选一个节点,

分两种情况讨论,(建或者不建神庙),然后DP,方程是一样的。

 

DP方程:

dp[i][0] = max(dp[i-1][0],dp[i-1][1]);

dp[i][1] = max(dp[i-1][0],dp[i-1][1]+zhi[i-1]);

*/
//下面是我的code:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define N 100005
typedef long long lld;
int n,v[N],P[N],num,in[N];
queueQ;
long long dp[N][2],dp1[N][2],zhi[N],fan[N],next[N],ans;

void dfs(int k)
{
    int t = next[k];
    if(v[t]) return ;
    P[++num] = t;
    v[t] = 1;
    dfs(t);
}

int main()
{
    while(~scanf("%d",&n)){
         int i,j,k;
         int a,b,c;
         while(!Q.empty()) Q.pop();
         memset(in,0,sizeof(in));
         for(i=1;i<=n;i++){
              scanf("%lld%lld%lld",&zhi[i],&fan[i],&next[i]);
              in[next[i]]++;
         }
         memset(v,0,sizeof(v));
         memset(dp,0,sizeof(dp));
         for(i=1;i<=n;i++){
              dp[i][1] = zhi[i];
              
              if(in[i] == 0){
                   Q.push(i);
                   in[i]--;
              }
         }
         
         while(!Q.empty()){
              int t = Q.front();
              Q.pop();
              k = next[t];
              
              v[t] = 1;
              dp[k][0] += max(dp[t][0],dp[t][1]);
              dp[k][1] += max(dp[t][0],dp[t][1] + fan[t]);
              
              if(--in[k] == 0) Q.push(k);
         } 
         
         ans = 0;
         int ll = 0;
         for(i=1;i<=n;i++){
              if(!v[i]){
                   num = 0;
                   P[++num] = i;
                   v[i] = 1;
                   dfs(i);
                   memcpy(dp1,dp,sizeof(dp));
                   dp1[P[2]][0] += dp1[P[1]][0];
                   dp1[P[2]][1] += dp1[P[1]][0];
                   for(j=3;j<=num;j++){
                        dp1[P[j]][0] += max(dp1[P[j-1]][0],dp1[P[j-1]][1]);
                        dp1[P[j]][1] += max(dp1[P[j-1]][0],dp1[P[j-1]][1]+fan[P[j-1]]);
                   }
                   dp[P[2]][0] += dp[P[1]][1];
                   dp[P[2]][1] += (dp[P[1]][1]+fan[P[1]]);
                   for(j=3;j<=num;j++){
                        dp[P[j]][0] += max(dp[P[j-1]][0],dp[P[j-1]][1]);
                        dp[P[j]][1] += max(dp[P[j-1]][0],dp[P[j-1]][1]+fan[P[j-1]]);
                   }
                   dp[P[num]][1] += fan[P[num]];
                   
                   long long tmp = 0;
                   for(j=1;j<=num;j++){
                        dp[P[j]][0] = max(dp[P[j]][0],dp1[P[j]][0]);
                        dp[P[j]][1] = max(dp[P[j]][1],dp1[P[j]][1]);
                        tmp = max(tmp,max(dp[P[j]][0],dp[P[j]][1]));
                   }
                   ans += tmp;
              }
         }
         printf("%lld\n",ans);
    }
    return 0;
}


 


 

你可能感兴趣的:(DP)