题意:
有p1个好人,p2个坏人
好人只说真话 坏人只说谎话
给出n句某个人说某个人是真人还是坏人
问是否存在好人和坏人方案的唯一解
有的话则升序输出好人
先用一个带权并查集维护一个联通块内的关系
然后dp[i][j]表示前i个联通块内有j个好人的方案
因为是唯一解
所以输出方案的时候倒过来推就可以了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair
#define pll pair
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007 ;
const double eps=1e-9;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 3e2+20;
const int maxm = 3e2+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
int fa[maxn<<1];
int d[maxn<<1];
int faf(int x)
{
if(fa[x]!=x)
{
int t = fa[x];
fa[x] = faf(t);
d[x] = d[x]^d[t];
}
return fa[x];
}
void un(int a,int b,int c)
{
int f1 = faf(a),f2 =faf(b);
if(f1!=f2)
{
fa[f2]=f1;
d[f2] = d[a]^d[b]^c;
}
}
vector<int>g[2][maxn<<1];
int num1[maxn<<1];
int num2[maxn<<1];
int dp[maxn<<1][maxn];
int rt[maxn<<1];
char s[100];
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int n,p1,p2;
while(~sddd(n,p1,p2),n||p1||p2)
{
r1(i,p1+p2)g[1][i].clear(),g[0][i].clear(),fa[i] = i,d[i] = 0,num1[i] = num2[i] = 0;
while(n--)
{
int a,b;
sdd(a,b);
ss(s);
if(s[0]=='n')un(a,b,1);
else un(a,b,0);
}
for(int i=1;i<=p1+p2;++i)
{
int x = faf(i);
if(d[i])++num1[x],g[1][x].pb(i);
else ++num2[x],g[0][x].pb(i);
}
mst(dp,0);
dp[0][0] = 1;
int c = 0;
for(int i=1;i<=p1+p2;++i)
{
if(faf(i)!=i)continue;
rt[++c] = i;
int mn = min(num1[i],num2[i]);
for(int j=p1;j>=mn;--j)
{
if(dp[c-1][j-num1[i]])
dp[c][j]+=dp[c-1][j-num1[i]];
if(dp[c-1][j-num2[i]])
dp[c][j]+= dp[c-1][j-num2[i]];
}
}
if(dp[c][p1]!=1)
{
puts("no");
continue;
}
vector<int>v;
while(c)
{
int r = rt[c];
if(dp[c-1][p1-num1[r]]==1)
{
int sz = g[1][r].size();
r0(i,sz)
{
v.pb(g[1][r][i]);
}
p1-=num1[r];
}
else
{
int sz = g[0][r].size();
r0(i,sz)v.pb(g[0][r][i]);
p1-=num2[r];
}
c--;
}
sort(all(v));
int sz = v.size();
r0(i,sz)
{
int ans = v[i];
ansn();
}
puts("end");
}
return 0;
}