2、总结:第一道树形dp,有点纠结
题意:公司聚会,员工与直接上司不能同时来,求最大权值和
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using namespace std; #define LL long long #define INF 0x3f3f3f3f const int N=6010; struct Eage { int from,to; int next; }eage[N<<1]; int val[N],out[N]; int dp[N][2]; //dp[i][0]表示i不去,dp[i][1]表示i去 int ans,head[N]; //head记录边的次序 void add_eage(int a,int b) //难点,理解边,构树 { eage[ans].from=a; eage[ans].to=b; eage[ans].next=head[b]; head[b]=ans++; } void dfs(int root) { dp[root][0]=0; dp[root][1]=val[root]; for(int i=head[root];i!=-1;i=eage[i].next){ //dfs所有指向root点的边 int s=eage[i].from; dfs(s); //状态转移。root去,他的下属就不能去;root不去,就取他下属去或不去的最大值 dp[root][0]+=max(dp[s][0],dp[s][1]); dp[root][1]+=dp[s][0]; } } int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } memset(out,0,sizeof(out)); memset(head,-1,sizeof(head)); int a,b; ans=0; while(scanf("%d%d",&a,&b),a||b){ out[a]++; add_eage(a,b); } int root; for(int i=1;i<=n;i++){ if(!out[i]){ //出度为0即根结点 root=i; break; } } memset(dp,0,sizeof(dp)); dfs(root); printf("%d ",max(dp[root][0],dp[root][1])); } return 0; }