题目地址: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 <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define N 100005
typedef long long lld;
int n,v[N],P[N],num,in[N];
queue<int>Q;
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;
}