Visiting Cows 拜访奶牛 bzoj-2060 Usaco-2010 Nov
题目大意:题目链接。
注释:略。
想法:看起来像支配集。
只是看起来像而已。
状态:dp[pos][flag]表示以pos为根的子树中,i选(不选)的最大收益。
转移:dp[pos][0]+=max(dp[to[i]][0],dp[to[i]][1]);dp[pos][1]+=dp[to[i]][0]。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 50010 using namespace std; int to[N<<2],nxt[N<<2],head[N],tot,dp[N][3]; inline char nc() { static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } int read() { int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=nc(); return x; } inline void add(int x,int y) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } void dfs(int pos,int fa) { dp[pos][1]=1; dp[pos][2]=0; for(int i=head[pos];i;i=nxt[i]) { if(to[i]==fa) continue; dfs(to[i],pos); dp[pos][1]+=dp[to[i]][2]; dp[pos][2]+=max(dp[to[i]][1],dp[to[i]][2]); } } int main() { int n=read(); for(int x,y,i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x); dfs(1,1); printf("%d ",max(dp[1][1],dp[1][2])); return 0; }
小结:树形dp裸题。