题意: n个人参加party,给出n个人的工作关系树,一个人和他的顶头上司不能同时参加,party达到的最大人数并判断邀请的最大人数名单是否唯一。
分析:
树状dp入门
dp[i][f],以i为根的子树,f=0,i不参加,f=1,i参加 能达到的最大人数。i参加i的孩子不能参加,i不参加,其孩子参不惨加都行(取最大值)。判断唯一性同理
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <algorithm> #include <map> using namespace std; #define maxn 65540 using namespace std; const int inf = 0x3f3f3f3f; const int N = 300; vector<int>e[N]; map<string,int>m; int dp[N][3]; bool f[N][3]; void dfs(int root) { for(int i=0;i<e[root].size();i++) { int son=e[root][i]; dfs(son); if(f[son][0]) f[root][1]=1; dp[root][1]+=dp[son][0]; if(dp[son][0]>dp[son][1]) { dp[root][0]+=dp[son][0]; if(f[son][0]) f[root][0]=1; } else { dp[root][0]+=dp[son][1]; if(dp[son][1]==dp[son][0]||f[son][1]) f[root][0]=1; } } } int main() { int n; while(~scanf("%d",&n) && n) { for(int i = 1;i<=n;i++) e[i].clear(); m.clear(); memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); for(int i=1;i<=n;++i) dp[i][1]=1; int num = 1; string s1,s2; cin>>s1; m[s1] = num; for(int i=1;i<n;i++) { cin>>s1>>s2; if(m[s1]==0) m[s1]=++num; if(m[s2]==0) m[s2]=++num; e[m[s2]].push_back(m[s1]); } dfs(1); if(dp[1][1]==dp[1][0]) printf("%d No\n",dp[1][1]); else if(dp[1][1]>dp[1][0]) printf("%d %s\n",dp[1][1],f[1][1]?"No":"Yes"); else printf("%d %s\n",dp[1][0],f[1][0]?"No":"Yes"); } return 0; }
原文:http://www.cnblogs.com/zsf123/p/4870222.html