UVA 1220 Party at Hali-Bula (树形DP)
求一棵数的最大独立集结点个数并判断方案是否唯一。
dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选。
决策:
当选择i时,就不能选择它的子结点。
当不选i时,它的子结点可选可不选。
判断唯一性:当选择的某个子节点方案不唯一,父节点的方案就不唯一,或者某个子节点选或不选方案数一样。
转移顺序:按照拓扑序转移或dfs都可以。
#include<bits/stdc++.h> using namespace std; const int maxn = 201; const int pick = 1; const int drop = 0; int d[maxn][2]; bool f[maxn][2];// NotUnique? int fa[maxn]; int deg[maxn]; int n; void topo() { queue<int> q; for(int i = 0; i < n; i++){ d[i][pick] = 1; d[i][drop] = 0; f[i][pick] = f[i][drop] = 0; if(deg[i] == 0){ q.push(i); } } while(q.size()){ int u = q.front(); q.pop(); int p = fa[u]; int &a = d[u][drop], &b = d[u][pick]; d[p][pick] += a; f[p][pick] |= f[u][drop]; if(a>b){ d[p][drop] += a; f[p][drop] |= f[u][drop]; }else { d[p][drop] += b; f[p][drop] |= a == b || f[u][pick]; } deg[p]--; if(deg[p] == 0) { q.push(p); } } } #define MP make_pair #define PB push_back #define fi first #define se second map<string,int> idx; int idx_cnt; int ID(string &x) { map<string,int>::iterator it = idx.find(x); if(it != idx.end()) return it->se; idx.insert(MP(x,idx_cnt)); return idx_cnt++; } string name; const int root = 0; bool read() { scanf("%d",&n); if(n == 0) return false; idx.clear(); cin>>name; idx.insert(MP(name,root)); idx_cnt = 1; fill(deg,deg+n,0); for(int i = 1; i < n; i++){ cin>>name; int v = ID(name); cin>>name; int p = ID(name); fa[v] = p; deg[p]++; } return true; } int main() { //freopen("in.txt","r",stdin); fa[root] = -1; while(read()){ topo(); int k = d[root][pick]>d[root][drop]?pick:drop; bool flag = d[root][k] != d[root][k^1] && !f[root][k]; printf("%d ",d[root][k]); if(flag) puts("Yes"); else puts("No"); } return 0; }