POJ_3342_Party at Hali-Bula_树形DP

时间:2023-03-10 05:19:10
POJ_3342_Party at Hali-Bula_树形DP

POJ_3342_Party at Hali-Bula_树形DP

题意:直接上司和本人不能同时参加,求最多参加人数,并回答是否唯一解。

分析:常规树形DP,需要再维护一下选/不选当前点取得最大值时是否为唯一解。

就是在转移时判断该状态是从哪转移过来的,最后答案同理。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 220
#define mem(x) memset(x,0,sizeof(x))
int head[N],to[N<<1],nxt[N<<1],flg,cnt,n;
int f[N],g[N],h[N],d[N];
char ch[N][N],a[N],b[N];
void add(int u,int v)
{
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int x,int y)
{
f[x]=1;d[x]=h[x]=1;
for(int i=head[x];i;i=nxt[i])
{
if(to[i]!=y)
{
dfs(to[i],x);
f[x]+=g[to[i]];
g[x]+=max(g[to[i]],f[to[i]]);
if(g[to[i]]>f[to[i]]&&d[to[i]]==0)d[x]=0;
else if(g[to[i]]<f[to[i]]&&h[to[i]]==0)d[x]=0;
else if(g[to[i]]==f[to[i]])d[x]=0;
if(d[to[i]]==0)h[x]=0;
}
}
}
int main()
{
while(scanf("%d",&n))
{
if(!n)break;
mem(d);mem(h);mem(f);mem(g);mem(head);
cnt=0;flg=0;
scanf("%s",ch[1]);
int now=1;
for(int i=1;i<n;i++)
{
scanf("%s%s",a,b);
int na=0,nb=0;
for(int j=1;j<=now;j++)
{
if(strcmp(ch[j],a)==0)
{
na=j;
}
if(strcmp(ch[j],b)==0)
{
nb=j;
}
}
if(!na)
{
na=++now;
strcpy(ch[now],a);
}
if(!nb)
{
nb=++now;
strcpy(ch[now],b);
}
add(na,nb);
add(nb,na);
}
dfs(1,0);
printf("%d ",max(f[1],g[1]));
if(f[1]==g[1])flg=1;
if(f[1]>g[1]&&h[1]==0)flg=1;
if(f[1]<g[1]&&d[1]==0)flg=1;
puts(flg?"No":"Yes");
}
}