Hoj 2500 Party at Hali-Bula
树形DP典型题。求最大独立集。
本题难在唯一性的判断上。
没接触树形DP以前,我以为本题的最大独立集的值应该是(1 + 3 + 5 + 7 + ...)层的和 与 (2 + 4 + 6 + 8 + 10 + ...)层的和的最大值。其实不对。
因为如果父节点是不选择的,而子节点既可以不选择也可以选择;但是如果父节点是选择的,那么子节点只能是不选择的。所以情况是多样化的,只能用树形DP来做。
代码如下:
[cpp]
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define Maxn 205
int n;
vector<int> p[Maxn];
map<string,int> m;
string s,s1,s2;
//dp[i][1]代表选择i点,dp[i][0]代表不选择
int dp[Maxn][2];
//flag[i][1]代表选择i点后,i为根的树的最大独立集不唯一
bool flag[Maxn][2];
void dfs(int u)
{
for(int i=0;i<p[u].size();i++)
{
int v = p[u][i];
dfs(v);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0],dp[v][1]);
if(dp[v][0] == dp[v][1] || (dp[v][0]>dp[v][1] && flag[v][0] == false) || (dp[v][0]<dp[v][1] && flag[v][1] == false))
{
flag[u][0] = false;
}
if(flag[v][0] == false)
{
flag[u][1] = false;
}
}
dp[u][1]++;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(scanf(" %d",&n)!=EOF && n!=0)
{
for(int i=0;i<Maxn;i++) p[i].clear();
m.clear();
memset(dp,0,sizeof(dp));
memset(flag,true,sizeof(flag));
int cnt = 1;
cin>>s;
m[s] = 1;
for(int i=1;i<n;i++)
{
cin>>s1>>s2;
if(m[s1] == 0) m[s1] = ++cnt;
if(m[s2] == 0) m[s2] = ++cnt;
p[m[s2]].push_back(m[s1]);
}
dfs(1);
printf("%d ",max(dp[1][0],dp[1][1]));
if((dp[1][0]>dp[1][1] && flag[1][0] == true) || (dp[1][0]<dp[1][1] && flag[1][1] == true))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define Maxn 205
int n;
vector<int> p[Maxn];
map<string,int> m;
string s,s1,s2;
//dp[i][1]代表选择i点,dp[i][0]代表不选择
int dp[Maxn][2];
//flag[i][1]代表选择i点后,i为根的树的最大独立集不唯一
bool flag[Maxn][2];
void dfs(int u)
{
for(int i=0;i<p[u].size();i++)
{
int v = p[u][i];
dfs(v);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0],dp[v][1]);
if(dp[v][0] == dp[v][1] || (dp[v][0]>dp[v][1] && flag[v][0] == false) || (dp[v][0]<dp[v][1] && flag[v][1] == false))
{
flag[u][0] = false;
}
if(flag[v][0] == false)
{
flag[u][1] = false;
}
}
dp[u][1]++;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(scanf(" %d",&n)!=EOF && n!=0)
{
for(int i=0;i<Maxn;i++) p[i].clear();
m.clear();
memset(dp,0,sizeof(dp));
memset(flag,true,sizeof(flag));
int cnt = 1;
cin>>s;
m[s] = 1;
for(int i=1;i<n;i++)
{
cin>>s1>>s2;
if(m[s1] == 0) m[s1] = ++cnt;
if(m[s2] == 0) m[s2] = ++cnt;
p[m[s2]].push_back(m[s1]);
}
dfs(1);
printf("%d ",max(dp[1][0],dp[1][1]));
if((dp[1][0]>dp[1][1] && flag[1][0] == true) || (dp[1][0]<dp[1][1] && flag[1][1] == true))
printf(&q
补充:软件开发 , C++ ,