这个题开始的时候没有什么头绪。
然后我们先用种类并查集来分组,然后用dp来判读是不是唯一,用p数组记录,便于输出值
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 615;
int dis[maxn],sum[maxn];//0为相同的,1为不同的
vector<int> b[maxn][2];//0,相同的,1,不同的。
int a[maxn][2],p[maxn][maxn];//对应的数量
int vis[maxn];
int dp[maxn][maxn/2];
vector<int> ans;
int findf(int k)
{
if(k==dis[k]) return k;
int t=dis[k];
dis[k]=findf(dis[k]);
sum[k]=(sum[k]+sum[t])%2;
return dis[k];
}
int main()
{
int n,p1,p2;
while(scanf("%d %d %d",&n,&p1,&p2)!=EOF)
{
if(n==0&&p1==0&&p2==0) break;
for(int i=0;i<=p1+p2;i++)
dis[i]=i;
memset(sum,0,sizeof(sum));
for(int i=0;i<n;i++)
{
int a,b;char s[10];
scanf("%d %d %s",&a,&b,s);
int flag=0;
if(s[0]=='n') flag=1;
int ra=findf(a);
int rb=findf(b);
if(ra!=rb)
{
if(ra<rb)
{
dis[rb]=ra;
sum[rb]=(sum[a]-flag-sum[b]+2)%2;
}
else {
dis[ra]=rb;
sum[ra]=(sum[b]+flag-sum[a]+2)%2;
}
}
}
for(int i=0;i<=p1+p2;i++)
{
b[i][0].clear();
b[i][1].clear();
a[i][0]=0;
a[i][1]=0;
vis[i]=0;
}
int cnt=1;
for(int i=1;i<=p1+p2;i++)
{
if(!vis[i])
{
int root=findf(i);
for(int j=i;j<=p1+p2;j++)
{
if(findf(j)==root)
{
vis[j]=1;
b[cnt][sum[j]].push_back(j);
a[cnt][sum[j]]++;
}
}
cnt++;
}
}
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<cnt;i++)
{
for(int j=0;j<=p1;j++)
{
if(j-a[i][0]>=0&&dp[i-1][j-a[i][0]])
{
dp[i][j]+=dp[i-1][j-a[i][0]];
p[i][j]=a[i][0];//p不能开一维数组,因为有可能又重复的。。//假是a[i][0]=0;那不就覆盖了么
}
if(j-a[i][1]>=0&&dp[i-1][j-a[i][1]])
{
dp[i][j]+=dp[i-1][j-a[i][1]];
p[i][j]=a[i][1];
}
}
}
if(dp[cnt-1][p1]!=1)
{
printf("no\n");
// continue;
}
else {
ans.clear();
// int k=p1,t=p[k],temp=cnt-1;
int t=p1;
for(int i=cnt-1;i>=1;i--)
{
int tmp=p[i][t];
if(tmp==a[i][0])
{
for(int j=0;j<a[i][0];j++)
ans.push_back(b[i][0][j]);
}
else
{
for(int j=0;j<a[i][1];j++)
ans.push_back(b[i][1][j]);
}
t=t-p[i][t];
}
/* while(k>0)
{
if(a[temp][0]==t)
{
for(int i=0;i<t;i++)
ans.push_back(b[temp][0][i]);
}
else if(a[temp][1]==t)
{
for(int i=0;i<t;i++)
ans.push_back(b[temp][1][i]);
}
temp--;
t=p[k-t];
k=k-t;
}*/
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
{
printf("%d\n",ans[i]);
}
printf("end\n");
}
}
return 0;
}
469

被折叠的 条评论
为什么被折叠?



