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;
}