ZOJ 3527 Shinryaku! Kero Musume(树DP)

来源:互联网 发布:淘宝客服在家可以做吗 编辑:程序博客网 时间:2024/06/04 17:52

2300 years ago, Moriya Suwako was defeated by Yasaka Kanako in the Great Suwa War. As the goddess of mountains in Gensokyo, she was planning to make a comeback and regain faith among humans.

TH_KeroSuwako.jpg

To achieve her great plan, she decides to build shrines in human villages. Of course, each village can bulid at most one shrine. If she builds a shrine in the i-th village, she can get Fifaith points.

Because of geological differences and the Quantum Entanglement theory, each village has one and only one "entangled" village Pi (it is a kind of one-way relationship). If Suwakobuilds shrines both in the i-th village and the Pi-th village, the faith she get from the i-th village will changes by Gi points (it can result to a negative value of faith points). If she only builds a shrine in the Pi-th village, but not in the i-th village, the faith she get will not changes.

Now, please help Suwako to find out the maximal faith points she can get.

Input

There are multiple test cases. For each test case:

The first line contains an integer N (2 <= N <= 100000) indicates the number of villages in Gensokyo. Then followed by N lines, each line contains three integers Fi (0 <= Fi <= 100000) Gi (-100000 <= Gi <= 100000) Pi (1 <= Pi <= N and Pi will not point to the i-th village itself).

Output

For each test case, output the maximal faith points that Suwako can get.

Sample Input

23 -1 22 -2 143 -2 24 -3 32 -1 15 -2 2

Sample Output

39

题意:在N个村庄选建圣地,如果在仅在PI建,不会损失满意度,如果在PI的儿子节点

也建会损失G满意度,问你选建时的最大满意度

分析:咋一看跟普通的树DP没啥区别,设dp[i][1]:为在第i个点建的最大满意度,dp[i][0]

不在第i个点建的最大满意度,但是存在环,我们来分析这个环的特点,每个村庄仅有一个"entangled" village

也就是说连边(有向)的时候每个点仅有一个入边,如果存在环的话,只有可能从环上的点开始向环外的点

边,而且不会存在双环。所以我们就在环上选定一点,分选与不选做两次树形DP,取最大值即可。

对于不在环上的点直接拓扑排序排除掉即可。

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )typedef long long LL;const LL INF = (1LL<<50);typedef pair<int,int>pil;const int maxn=1e5+100;struct node{    int to,next;    int val;}e[maxn];int n,tot;LL dp[maxn][2];int head[maxn],in[maxn];int vis[maxn],a[maxn];void addedge(int u,int v,int w){    e[tot].to=v;e[tot].next=head[u];    e[tot].val=w;head[u]=tot++;}void dfs(int u,int fa){    dp[u][0]=0;    dp[u][1]=a[u];    for(int i=head[u];i!=-1;i=e[i].next)    {        int to=e[i].to;        if(to!=fa)           dfs(to,fa);        dp[u][0]+=max(dp[to][0],dp[to][1]);        dp[u][1]+=max(dp[to][0],dp[to][1]+e[i].val);    }}LL solve(int u){    LL ans1=0,ans2=0;    dp[u][0]=0;dp[u][1]=-INF;    for(int i=head[u];i!=-1;i=e[i].next)    {        int v=e[i].to;        dfs(v,u);        ans1+=max(dp[v][0],dp[v][1]);    }    dp[u][0]=-INF;dp[u][1]=a[u];    for(int i=head[u];i!=-1;i=e[i].next)    {        int v=e[i].to;        dfs(v,u);        ans2+=max(dp[v][0],dp[v][1]+e[i].val);    }    return max(ans1,ans2);}bool ok(int u,int fa){    vis[u]=1;    for(int i=head[u];i!=-1;i=e[i].next)    {        int to=e[i].to;        if(to==fa)            return true;        if(ok(to,fa))            return true;    }    return false;}void topsort(){    queue<int>q;    for(int i=1;i<=n;i++)        if(!in[i]) q.push(i);    while(!q.empty())    {        int x=q.front();        q.pop();        vis[x]=1;        for(int i=head[x];i!=-1;i=e[i].next)        {            int to=e[i].to;            in[to]--;            if(!in[to])               q.push(to);        }    }}int main(){    int x,y,w;    while(~scanf("%d",&n))    {        CLEAR(head,-1);tot=0;        CLEAR(vis,0);CLEAR(in,0);        for(int i=1;i<=n;i++)        {            scanf("%d%d%d",&a[i],&w,&y);            addedge(y,i,w);in[i]++;        }        topsort();        LL ans=0;        for(int i=1;i<=n;i++)        {           if(!vis[i]&&ok(i,i))               ans+=solve(i);        }        printf("%lld\n",ans);    }    return 0;}


1 0
原创粉丝点击