求一棵數的最大獨立集結點個數並判斷方案是否唯一。
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; }