http://poj.org/problem?id=1417 题目链接这里
又是一题种类并查集,因为poj崩掉了,我就当ac了; 以下是代码;
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; int f[1010], relation[1010], type1[1010], type2[1010]; // relation是种类并查集关系, //type1 纪录与根节点的同类,type2纪录另一类 int dp[1010][1010]; int parent[1010]; //存根节点 int vis[1010]; int ans[1010]; int Find(int x) { if(f[x] == x) return x; int tmp = f[x]; f[x] = Find(f[x]); relation[x] = relation[x] ^ relation[tmp]; //种类并查集最神奇的地方就是这个关系, //参考了大佬的代码才写出来,比较玄学,这种两个种类的应该就是这个关系写法 return f[x]; } void Union(int x, int y, int rela) { int rx = Find(x); int ry = Find(y); if(rx != ry) { f[rx] = ry; relation[rx] = relation[x]^relation[y]^rela;//合并根节点,注意关系域的转移 } } int main() { int n, p1, p2; while(scanf("%d%d%d", &n, &p1, &p2) && (p1 + p2 + n)) { for(int i = 1; i <= p1 + p2; i++) { f[i] = i, relation[i] = 0, type1[i] = 0, type2[i] = 0; vis[i] = 0; } memset(dp, 0, sizeof(dp)); for(int i = 0; i < n; i++) { int a, b; char s[8]; scanf("%d%d%s", &a, &b, s); if(s[0] == 'y') Union(a, b, 0);//同类会说yes else Union(a, b, 1); } int cnt = 1; for(int i = 1; i <= p1 + p2; i++) { if(!vis[i]) { int fa = Find(i); for(int j = i; j <= p1 + p2; j++) { if(Find(j) == fa && !vis[j]) { vis[j] = 1; if(relation[j] == 0) type1[cnt]++; else type2[cnt]++; // 找出根结点并且纪录两个种类的数目 } } parent[cnt++] = fa; } } dp[0][0] = 1; //方案数背包,看看是不是只有一种方案能满足凑出p1来,凑p2也可以 for(int i = 1; i < cnt; i++) { int Min = min(type1[i], type2[i]); for(int j = p1; j >= Min; j--) { if(dp[i - 1][j - type1[i]]) { dp[i][j] += dp[i - 1][j - type1[i]]; } if(dp[i - 1][j - type2[i]]) { dp[i][j] += dp[i - 1][j - type2[i]]; } //printf("%d %d %d\n",i, j, dp[i][j]); } } // printf("%d\n", dp[cnt-1][p1]); // printf("cnt %d", cnt); if(dp[cnt-1][p1] != 1) { printf("no\n"); continue; } int num = 0; int lost = p1; // 路径回溯找到节点存起来 for(int i = cnt - 1; i >= 1; i--) { if(dp[i - 1][lost - type1[i]] == 1) { for(int j = 1; j <= p1 + p2; j++) { if(Find(j) == parent[i] && relation[j] == 0) ans[num++] = j; } lost -= type1[i]; } else { for(int j = 1; j <= p1 + p2; j++) if(Find(j) == parent[i] && relation[j] == 1) ans[num++] = j; lost -= type2[i]; } } sort(ans, ans + num); for(int i = 0; i < num; i++) printf("%d\n", ans[i]); printf("end\n"); } return 0; }