传送门(洛谷)
题目描述:
输入数据:
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
输出数据:
5
一道树形dp题
以f[i][1]表示i号人要去,f[i][0]表示i号不去
以下转移方程(v是x的下属):
f[x][0]+=max(f[v][1],f[v][0]);
表示x不去时,下属来还是不来,因为我们找最大值,当x要来时,他的下属一定不来
f[x][1]+=f[v][0];
Code
/***********************************
* Problem P1352 没有上司的舞会 *
* User mzg1824_Ty *
* Time 2019.5.17 *
* Algorthim 树形动规 *
************************************/
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define don(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e3+10;
int n,m,cnt=0;
int f[maxn][2],h[maxn],rd[maxn];
int head[maxn];
template <class t> inline void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
template <class t> inline void write(t x)
{
if(x<0){putchar('-');x=~x+1;}
if(x>9) write(x/10);
putchar(x%10+48);
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
struct node{
int v,nex;
}e[maxn<<1];
void add(int u,int v) {
e[++cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void readdata()
{
read(n);
rep(i,1,n) read(h[i]);
while(1) {
int x,y;
read(x),read(y);
rd[x]++; //找根,就是那个最牛的人
if(x==0 && y==0) break;
add(y,x);//邻接表存储y号的下属
}
}
inline void dfs(int x) {
for(int i=head[x];i;i=e[i].nex)
{
int v=e[i].v;
dfs(v);
f[x][0]+=max(f[v][1],f[v][0]);
f[x][1]+=f[v][0];
}
f[x][1]+=h[x];
}
void work()
{
int rt=0;
rep(i,1,n) {
if(rd[i]==0) rt=i;
}
dfs(rt);
int ans=max(f[rt][1],f[rt][0]);
write(ans);
}
int main()
{
freopen("input.txt","r",stdin);
readdata();
work();
return 0;
}