[题解] UVA1220 Hali-Bula的晚会 Party at Hali-Bula
UVA1220 Hali-Bula的晚会 Party at Hali-Bula
一个树形\(DP\)
没有上司的舞会升级版
和这道题第一问几乎一样,或者说变简单了
需要记录选与不选 \(0/1\),这道题只是多了一个唯一性问题(\(d\) 数组记录唯一性):
- 对于 \(f[u][1]\)
\(f[u][1]=\sum{f[v][0]}\)
对于所有的 \(d[v][0]\),如果有一个方案不唯一,那么 \(d[u][1]=1\)
可以用 按位或 来解决这种问题。
- 对于 \(f[u][0]\)
\(f[u][0]=\sum{max(f[v][0],f[v][1])+1}\)
只需要看看 \(f[u][0]\) 的 \(max\) 取到了哪一个,只要有一个是不唯一的,那么 \(d[u][1]=1\)
也可以用 按位或 来解决。
最后统计答案类似。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template <typename T>
inline T read(){
char ch=getchar();T x=0;bool fl=false;
while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+(ch^48);ch=getchar();
}
return fl?-x:x;
}
#include <map>
const int maxn = 210 , INF = 0x3f3f3f3f;
struct edge{
int to,nxt;
}e[maxn<<1];
int head[maxn],cnt=0;
inline void link(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
map <string,int> mp;
int idcnt=0;
inline int id(string s){
if(!mp[s])mp[s]=++idcnt;return mp[s];
}
int f[maxn][2],d[maxn][2];//1:不唯一 or 0:唯一
void dfs(int u){
f[u][0]=0;f[u][1]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
dfs(v);
//--------
f[u][1]+=f[v][0];d[u][1]|=d[v][0];
f[u][0]+=max(f[v][0],f[v][1]);
if(f[v][0]==f[v][1])d[u][0]=1;
else if(f[v][0]<f[v][1])d[u][0]|=d[v][1];
else d[u][0]|=d[v][0];
}
}
int n;
inline void clear(){
mp.clear();idcnt=0;cnt=0;
memset(head,0,sizeof head);
memset(f,0,sizeof f);
memset(d,0,sizeof d);
}
int main(){
while(scanf("%d",&n)==1 && n!=0){
string boss;cin>>boss;
int rt=id(boss);
for(int i=1;i<n;i++){
string a,b;cin>>b>>a;
int u=id(a),v=id(b);link(u,v);
}
dfs(rt);
printf("%d ",max(f[rt][0],f[rt][1]));
if(f[rt][0]==f[rt][1])puts("No");
else if(f[rt][0]<f[rt][1])puts(d[rt][1]?"No":"Yes");
else puts(d[rt][0]?"No":"Yes");
clear();
}
return 0;
}