您的位置:首页 > 其它

Hali-Bula的晚会(UVa1220)详细题解

2017-05-11 18:23 267 查看

累加器传送门:

http://blog.csdn.net/NOIAu/article/details/71775000

题目传送门:https://vjudge.net/problem/UVA-1220

题目大意是说一个公司的员工成树形分布,每个人只有一个直属上司,现在要开个party,不能让一个人和他的直接老板同时出现在party上,问最多能选多少人,并问选择是否唯一

用dp[i][j]表示最大人数,其中i为第i个点,其中j可以为0或者为1,表示第i个人选或者不选,即选或者不选i的以i为根的子树的最优值,另一个f[i][j]表示唯不唯一,i和j的含义dp数组一样

dp[i][1]的计算

因为选了第i个点,所以i的直接下属都不能选,所以dp[i][1]的值应该为所有下属不选(dp[son][0])的值之和,再加上1(因为选了i)

f[i][1]的计算

当所有的f[son][0]都唯一的时候,f[i][1]唯一

dp[i][0]的计算

不选i,所以他的直接下属是自由的,所以可以邀请也可以不邀请,所以应该把每个son节点的选(dp[son][1])或者不选(dp[son][0])的大的那个值,将每一个son的大的那个值加起来即可

f[i][0]的计算

如果选一个子点(dp[son][1])和不选一个子点(dp[son][0])所邀请的人是一样的,所以此时方案不唯一,还有一种情况是如果在计算dp[i][0]的时候每一个son节点的max值选择的时候,选择的那个的f是不唯一的,那么f[i][0]是不唯一的,比如(dp[son][0]>dp[son][1],且f[son][0]不唯一,则f[i][0]不唯一)

下面上代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#include<vector>
#define MAXN 300+10
using namespace std;

map<string,int>m;
vector<int>v[MAXN];
int tail;
int dp[MAXN][5],f[MAXN][5];
int n;
bool init(){
m.clear();
tail=0;
scanf("%d",&n);
if(n==0) return false;
for(int i=0;i<n;i++) v[i].clear();
string s,ss;
cin>>s;
m[s]=tail++;
for(int i=1;i<=n-1;i++){
cin>>s;
cin>>ss;
if(m.find(s)==m.end()){
m[s]=tail++;
}
if(m.find(ss)==m.end()){
m[ss]=tail++;
}
v[m[ss]].push_back(m[s]);
}
for(int i=0;i<=n;i++){
f[i][0]=1;
f[i][1]=1;
}
memset(dp,0,sizeof(dp));
return true;
}

void dpp(int u){
if(v[u].empty()){
dp[u][1]=1;
dp[u][0]=0;
return ;
}
int son=v[u].size();
for(int i=0;i<son;i++){
int to=v[u][i];
dpp(to);
dp[u][1]+=dp[to][0];
if(dp[to][0]>dp[to][1]){
dp[u][0]+=dp[to][0];
if(f[to][0]==0) f[u][0]=0;
}else{
dp[u][0]+=dp[to][1];
if(f[to][1]==0) f[u][0]=0;
if(dp[to][0]==dp[to][1]) f[u][0]=0;
}
}
dp[u][1]++;
}

void print(){
if(dp[0][1]>dp[0][0]){
printf("%d ",dp[0][1]);
if(f[0][1]){
printf("Yes\n");
}else{
printf("No\n");
}
}
if(dp[0][1]<dp[0][0]){
printf("%d ",dp[0][0]);
if(f[0][0]){
printf("Yes\n");
}else{
printf("No\n");
}
}
if(dp[0][1]==dp[0][0]){
printf("%d ",dp[0][0]);
printf("No\n");
}
}

int main(){
freopen("in.in","r",stdin);
while(init()){
dpp(0);
print();
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: