传送门
思路:
普通的树型动规,可参考 P2016 战略游戏 。
标程:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<vector> #include<stack> #include<deque> #include<queue> #include<map> #include<set> using namespace std; #define max(a,b) ((a)>(b)?(a):(b)) #define maxn 6005 typedef long long LL; LL n,root,f[maxn][2],w[maxn];//w[i]为每个职员的欢乐度 bool bo[maxn]; struct hh { LL num,son[maxn]; }t[maxn]; inline LL read() { LL kr=1,xs=0;char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline void dp(LL x) { for(LL i=1;i<=t[x].num;i++) { dp(t[x].son[i]); f[x][0]+=max(f[t[x].son[i]][1],f[t[x].son[i]][0]); f[x][1]+=f[t[x].son[i]][0]; } }//普通的树型动规 int main() { LL u,v; n=read(); for(LL i=1;i<=n;i++) { w[i]=read();f[i][1]=w[i]; } do { u=read();v=read();//u→v t[v].num++; t[v].son[t[v].num]=u; bo[u]=true; }while(u&&v); root=0; while(bo[root]) root++; dp(root); printf("%lld ",max(f[root][1],f[root][0])); return 0; }