题意:n个人形成一个关系树,每个节点代表一个人,节点的父节点表示这个人的唯一上司,只有根没有上司。要求从这n个人中选择一部分,使得任意两个人之间没有直接的上下级关系,问最多可以选多少人?并且判断最优方案是否唯一,是则Yes,否则No。
题解:dp[i][0]表示不选择 i 时,以它为根的子树最多可选出的人数;dp[i][1]表示选择 i 时,以它为根的子树最多可选出的人数。sole[i][0]表示不选择 i 时,最优方案是否唯一;sole[i][1]表示选择 i 时,最优方案是否唯一。
PS:此ppt上有详细说明http://wenku.baidu.com/view/84164e1a227916888486d7d6.html?from=rec&pos=4&weight=1
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
map<string,int> name;
map<string,int>::iterator it;
int dp[500][2];
bool sole[500][2], visit[500];
struct Edge { int v, next; } edge[500];
int head[500], E, n;
void add_edge(int u, int v)
{
edge[E].v = v;
edge[E].next = head[u];
head[u] = E++;
}
void DFS(int u, int father)
{
if(visit[u]) return;
if(head[u] == -1)
{
dp[u][0] = 0;
dp[u][1] = 1;
sole[u][0] = sole[u][1] = true;
visit[u] = true;
return;
}
visit[u] = true;
dp[u][0] = 0; dp[u][1] = 1;
sole[u][0] = sole[u][1] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(v == father) continue;
if(!visit[v]) DFS(v, u);
dp[u][0] += max(dp[v][0], dp[v][1]);
dp[u][1] += dp[v][0];
if(dp[v][0] > dp[v][1] && !sole[v][0]) sole[u][0] = false;
if(dp[v][0] < dp[v][1] && !sole[v][1]) sole[u][0] = false;
if(dp[v][0] == dp[v][1]) sole[u][0] = false;
if(sole[v][0] == false) sole[u][1] = false;
}
}
int main()
{
string employee, boss;
while(cin >> n)
{
if(n == 0) break;
int i, c, u, v;
c = E = 0;
memset(head, -1, sizeof(head));
memset(visit, 0, sizeof(visit));
name.clear();
cin >> boss;
name.insert(pair<string, int>(boss, 0));
for(i = 1; i < n; i++)
{
cin >> employee >> boss;
it = name.find(employee);
if(it == name.end())
{
name.insert(pair<string, int>(employee, ++c));
u = c;
}
else u = it->second;
it = name.find(boss);
if(it == name.end())
{
name.insert(pair<string, int>(boss, ++c));
v = c;
}
else v = it->second;
add_edge(u, v);
add_edge(v, u);
}
DFS(0, -1);
if(dp[0][0] > dp[0][1])
cout << dp[0][0] << (sole[0][0] ? " Yes" : " No") << endl;
else if(dp[0][0] < dp[0][1])
cout << dp[0][1] << (sole[0][1] ? " Yes" : " No") << endl;
else
cout << dp[0][0] << " No" << endl;
}
}