您的位置:首页 > 其它

uva 1220 Party at Hali-Bula 树形DP

2016-08-27 16:35 323 查看
题目链接

思路:本题几乎就是树的最大独立集问题,只不过多了一个判断解的唯一性的要求。针对这种情况,可以做如下定义:

(1)d(u,0),f(u,0)分别表示以u为根的子树中,不选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);

(2)d(u,1),f(u,1)分别表示以u为根的子树中,选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);

相应的,状态转移方程也要有两种情况:

(1)d(u,1)的计算:由于选择了u,那么u的子结点都不能选。因此,d(u,1)=sum{d(v,0)|v是u的子结点}。当且仅当所有的f(v,0)=1时,f(u,1)才是1.

(2)d(u,0)的计算:因为u没有选,因此它的子结点可选可不选。因此,d(u,0)=sum{max(d(v,0),d(v,1))}。公式中先找到每个子结点的最大值,再求和。唯一性的判断:(i)如果d(v,0)==d(v,1),那么方案不唯一;(ii)如果max取到的那个结点的f=0,方案也不唯一。

#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<sstream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<climits>
#include<cctype>
#include<bitset>
#include<set>
using namespace std;
#define mod 1000000007
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
typedef long long LL;

const int MAXN=205;
vector<int>son[MAXN];
string a,b;
int n;
int u[MAXN][2],f[MAXN][2];
void dfs(int x){
if(son[x].empty()){
u[x][1]=1;
u[x][0]=0;
return ;
}
u[x][1]++;
for(int i=0;i<son[x].size();i++){
dfs(son[x][i]);
if(f[son[x][i]][0])
f[x][1]=1;
u[x][1]+=u[son[x][i]][0];
if(u[son[x][i]][0]>u[son[x][i]][1]){
if(f[son[x][i]][0]){
f[x][0]=1;
}
u[x][0]+=u[son[x][i]][0];
}
else {
if(u[son[x][i]][0]==u[son[x][i]][1]||f[son[x][i]][1]){
f[x][0]=1;
}
u[x][0]+=u[son[x][i]][1];
}
}

}

int main()
{
while(~scanf("%d",&n)&&n){
int cnt=0;
memset(u,0,sizeof(u));
memset(f,0,sizeof(f));
map<string,int>m;
cin>>a;
m[a]=++cnt;
for(int i=1;i<n;i++){
cin>>a>>b;
if(!m[a])m[a]=++cnt;
if(!m[b])m[b]=++cnt;
son[m[b]].push_back(m[a]);
}
dfs(1);
if(u[1][0]>u[1][1]){
cout<<u[1][0]<<" ";
if(f[1][0]==0)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
else if(u[1][0]<u[1][1]){
cout<<u[1][1]<<" ";
if(f[1][1]==0)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
else {
cout<<u[1][0]<<" ";
cout<<"No"<<endl;
}
for(int i=1;i<=n;i++){
son[i].clear();
}
}
return 0;
}


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