说no的必定是不同阵营的,说yes的必定是同一阵营的,我们把已经确定是同一阵营的归到一起,最后看那些不同的集合能不能拼成我们所需要的。如果用并查集来做,我们需要加一个记录长度的数组。普通并查集无法完成排除数据相反的点并成一个的情况,可以把每个点的根节点设为0或1,表示与上一段是不是同类,每一段构造出一个数组,然后记录数组的个数和所包含的值,然后利用背包的思路构建dp[i][j]找出dp[n][p1];看其是否为1,是1的话就通过储存在b中的那些数输出结果,不是就不输出。
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=600+10;
int f[maxn];
int rank1[maxn];
int a[maxn][2];
vector <int> b[maxn][2];
int dp[maxn][maxn/2];
bool visit[maxn];
int last[maxn][maxn/2];
int find(int x)
{
if(f[x]==-1) return x;
int tmp=find(f[x]);
rank1[x]+=rank1[f[x]];
rank1[x]%=2;
return f[x]=tmp;
}
int main()
{
int n,p1,p2;
int i,j,k;
while(scanf("%d%d%d",&n,&p1,&p2)&&(n||p1||p2))
{
//注意做完之后检查有0的情况是否符合
memset(f,-1,sizeof(f));
memset(rank1,0,sizeof(rank1));
for(i=0;i<n;i++)
{
int x,y;
char a[3];
scanf("%d%d%s",&x,&y,&a);
int temp;
if(!strcmp(a,"yes"))
{
temp=0;
}
else if(!strcmp(a,"no"))
{
temp=1;
}
int x1=find(x),y1=find(y);
if(x1!=y1)
{
f[x1]=y1;
rank1[x1]=(rank1[x]-rank1[y]+2+temp)%2; //这边为什么要用rank1[x],rank1[y];
}
}
for(i=0;i<maxn;i++)
{
b[i][0].clear();
b[i][1].clear();
a[i][0]=0;
a[i][1]=0;
}
memset(visit,false,sizeof(visit));
int an=1;
for(i=1;i<=p1+p2;i++)
{
if(!visit[i])
{
int pan=find(i);
for(j=i;j<=p1+p2;j++)
{
if(pan==find(j))
{
visit[j]=true;
b[an][rank1[j]].push_back(j);
a[an][rank1[j]]++;
}
}
an++;
}
}
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(i=1;i<an;i++)
for(j=p1;j>=0;j--)
{
if(j>=a[i][0]&&dp[i-1][j-a[i][0]])
{
dp[i][j]+=dp[i-1][j-a[i][0]];
last[i][j]=j-a[i][0]; //last表示上一个是什么
}
if(j>=a[i][1]&&dp[i-1][j-a[i][1]])
{
dp[i][j]+=dp[i-1][j-a[i][1]];
last[i][j]=j-a[i][1];
}
}
if(dp[an-1][p1]!=1)
printf("no\n");
else
{
vector <int> ans;
ans.clear();
int t=p1;
for(i=an-1;i>=1;i--)
{
int tmp=t-last[i][t];
if(tmp==a[i][0])
{
for(j=0;j<a[i][0];j++)
ans.push_back(b[i][0][j]);
}
else if(tmp==a[i][1])
{
for(j=0;j<a[i][1];j++)
ans.push_back(b[i][1][j]);
}
t=last[i][t];
}
sort(ans.begin(),ans.end());
for(i=0;i<ans.size();i++)
printf("%d\n",ans[i]);
printf("end\n");
}
}
return 0;
}