uva1220--树的最大独立集+判重
题意是挑选尽量多的人,并且每个人都不和他的父节点同时出现,很明显的最大独立集问题,难点在于如何判断方案是否唯一。
详情请见刘汝佳《算法竞赛入门经典--第二版》P282
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<cstring> #include<cmath> #include<queue> #define INF 1e6 using namespace std; const int maxn = 205; char ch[105],fa[105]; char trie[maxn][105]; int k; int d[maxn][2],f[maxn][2]; vector<int> g[maxn]; int ID(char *s)//给每个字符串分配ID; { int i = 0; for(i = 0; i < k; ++i) { if(strcmp(s,trie[i]) == 0) { return i; } } if(i == k) strcpy(trie[k],s); k++; return k-1; } int dp(int u,int x) { if(d[u][x]!=-1) return d[u][x];//记忆化 if(x == 1){ int sum = 1; f[u][1] = 1; if(g[u].size() == 0) return d[u][1] = 1; for(int i = 0; i < g[u].size(); ++i) { sum+=dp(g[u][i],0); if(f[g[u][i]][0] == 0) { f[u][1] = 0; } } return d[u][1] = sum; } else { int sum = 0; f[u][0] = 1; if(g[u].size() == 0) return d[u][0] = 0; for(int i = 0; i < g[u].size(); ++i) { int p = dp(g[u][i],0),q = dp(g[u][i],1); if(p == q) { sum+=p; f[u][0] = 0; } else if(p > q) { sum+=p; if(f[g[u][i]][0] == 0) f[u][0] = 0; } else if(p < q) { sum+=q; if(f[g[u][i]][1] == 0) f[u][1] = 0; } } return d[u][0] = sum; } } int main() { //freopen("in","r",stdin); int n; while(~scanf("%d",&n)&&n) { int from,to; k = 0; scanf("%s",ch); ID(ch);//big boss是0号 for(int i = 1; i < n; ++i) { scanf("%s%s",ch,fa); from = ID(ch); to = ID(fa); g[to].push_back(from); } //printf("%d\n",g[0].size()); memset(d,-1,sizeof(d)); dp(0,0); dp(0,1); if(d[0][0] > d[0][1]) { printf("%d ",d[0][0]); if(f[0][0]) puts("Yes"); else puts("No"); } else if(d[0][0] < d[0][1]) { printf("%d ",d[0][1]); if(f[0][1]) puts("Yes"); else puts("No"); } else { printf("%d ",d[0][1]); puts("No"); } for(int i = 0; i < n; ++i) g[i].clear(); } }