开始被这道题坑了,觉得一个上司的下属不止一个,然后就把它转成了二叉树做,然后把自己都绕进去了。
其实,这道题用原图dp就可以了。
dp方程: f[v][1]+=f[v.son][0];
f[v][0]+=max{f[v.son][0],f[v.son][1]};
我的代码是直接建立的有向边,直接遍历所有的边。
附上代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
struct node{int to,next;};
node e[100861];
int head[6118];
int n,a[6118];
int f[6118][2];
int size;
void tjb(int x,int y)
{
size++;
e[size].next=head[x];
head[x]=size;
e[size].to=y;
}
int dp(int v,int p )
{
if(f[v][p]==-1)
{
f[v][p]=0;
if(p)
{
for(int i=head[v];i;i=e[i].next)
f[v][p]+=dp(e[i].to,0);
f[v][p]+=a[v];
}
else
for(int i=head[v];i;i=e[i].next)
f[v][p]+=max(dp(e[i].to,1),dp(e[i].to,0));
}
return f[v][p];
}
int ru[6118];
int main()
{
while(cin>>n)
{
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int x,y;
memset(ru,0,sizeof(ru));
size=0;
scanf("%d%d",&x,&y);
while(x!=0&&y!=0)
{
tjb(y,x);
ru[x]++;
scanf("%d%d",&x,&y);
}
int rep=0;
for(int i=1;i<=n;i++)
if(ru[i]==0) rep=i;
int ans=0;
memset(f,-1,sizeof(f));
ans=dp(rep,0);
ans=max(ans,dp(rep,1));
cout<<ans<<endl;
}
return 0;
}