权值并查集
之后就是一个简单的背包
之后逆向输出,显然若当前唯一则前置也必定唯一
#include<cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
using namespace std;
#define fst first
#define sec second
#define sci(num) scanf("%d",&num)
#define scl(num) scanf("%lld",&num)
#define mem(a,b) memset(a,b,sizeof a)
#define cpy(a,b) memcopy(a,b,sizeof b)
typedef long long LL;
typedef pair<int,int> P;
const int MAX_N = 1010;
const int MAX_M = 10000;
char str[100];
int Fa[MAX_N],R[MAX_N];
int N,M,p1,p2;
vector<int> ss[2][MAX_N];
int DP[MAX_N][MAX_N];
int vis[MAX_N];
void init() {
mem(DP,0);
mem(vis,0);
for (int i = 0;i <= N;i++) {
Fa[i] = i;
R[i] = 0;
ss[0][i].clear();
ss[1][i].clear();
}
DP[0][0] = 1;
}
int Find(int x) {
if (Fa[x] != x) {
int p = Fa[x];
Fa[x] = Find(Fa[x]);
R[x] = R[x] ^ R[p];
}
return Fa[x];
}
int main() {
while (~scanf("%d%d%d",&M,&p1,&p2)) {
N = p1 + p2;
if (N == 0) break;
init();
for (int i = 0;i < M;i++) {
int u,v;
scanf("%d%d%s",&u,&v,&str);
int k = str[0] == 'n';
int uf = Find(u);
int vf = Find(v);
if (uf != vf) {
Fa[uf] = vf;
R[uf] = R[u] ^ R[v] ^ k;
}
}
for (int i = 1;i <= N;i++) {
Find(i);
ss[R[i]][Fa[i]].push_back(i);
}
for (int i = 1;i <= N;i++) {
int d1 = ss[0][i].size();
int d2 = ss[1][i].size();
for (int j = 0;j <= p1;j++) {
if (d1 == d2 && d1 == 0) {
DP[i][j] = DP[i - 1][j];
continue;
}
if (j -d1 >= 0) {
DP[i][j] += DP[i - 1][j -d1];
}
if (j -d2 >= 0) {
DP[i][j] += DP[i - 1][j -d2];
}
}
}
if (DP[N][p1] != 1) {
printf("no\n");
} else {
vector<int> ans;
ans.clear();
for (int i = N;i >= 1;i--) {
int d1 = ss[0][i].size();
int d2 = ss[1][i].size();
if (d1 + d2 == 0) continue;
if (p1 - d1 >= 0 && p2 - d2 >= 0 && DP[i- 1][p1 - d1] == 1) {
for (int k = 0;k < ss[0][i].size();k++) {
ans.push_back(ss[0][i][k]);
}
p1 -= d1;
p2 -= d2;
} else {
for (int k = 0;k < ss[1][i].size();k++) {
ans.push_back(ss[1][i][k]);
}
p1 -= d2;
p2 -= d1;
}
}
sort(ans.begin(),ans.end());
for (int i = 0;i < ans.size();i++) {
printf("%d\n",ans[i]);
}
printf("end\n");
}
}
return 0;
}