poj 1417

跟poj 1112还有 cf edu 87 e是一模一样的思路

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <math.h>
#include <stack>

#define INF 0x3f3f3f3f
#define IMAX 2147483646
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int

using namespace std;

const int maxn = 666;

int pre[maxn], rrank[maxn];

int find(int x) {
	if (x != pre[x]) {
		int px = find(pre[x]);
		rrank[x] ^= rrank[pre[x]];
		pre[x] = px;
	}
	return pre[x];
}

void jion(int x, int y, int d) {
	int px = find(x);
	int py = find(y);
	if (px != py) {
		pre[py] = px;
		rrank[py] = rrank[x] ^ rrank[y] ^ d;
	}
}

int m, p, q,x,y,d,tot;
char str[5];
int gg[maxn], jj[maxn][maxn],tag[maxn][2],
dp[maxn][maxn], cc[maxn][2];

int main() {
	while (scanf("%d%d%d", &m, &p, &q),m+p+q!=0) {
		for (int i = 1; i <= p + q; i++)
			rrank[i] = 0, pre[i] = i;
		while (m--) {
			scanf("%d%d%s", &x, &y, str);
			d = (str[0] == 'y' ? 0 : 1);
			jion(x, y, d);
		}
		memset(gg, 0, sizeof(gg)); 
		memset(jj, 0, sizeof(jj));
		memset(tag, 0, sizeof(tag));
		memset(dp, 0, sizeof(dp));
		memset(cc, 0, sizeof(cc));

		tot = 0;
		for (int i = 1; i <= p + q; i++)
			if (find(i) == i)
				gg[i] = ++tot;
		for (int i = 1; i <= p + q; i++)
			tag[gg[find(i)]][rrank[i]]++;

		dp[0][0] = 1;
		for (int i = 1; i <= tot; i++) 
			for (int j = 0; j <= p + q; j++) {
				if (j - tag[i][0] >= 0 && dp[i - 1][j - tag[i][0]]) { 
					dp[i][j] += dp[i - 1][j - tag[i][0]];
					jj[i][j] = tag[i][0];
				}
				if (j - tag[i][1] >= 0 && dp[i - 1][j - tag[i][1]]) {
					dp[i][j] += dp[i - 1][j - tag[i][1]];
					jj[i][j] = tag[i][1];
				}
			}

		if (dp[tot][p] != 1) {
			printf("no\n");
			continue;
		}

		for (int i = tot, j = p; j > 0 && i > 0; i--) {
			if (jj[i][j] == tag[i][0])
				cc[i][0] = 1;
			else
				cc[i][1] = 1;
			j -= jj[i][j];
		}
		for (int i = 1; i <= p + q; i++)
			if (cc[gg[find(i)]][rrank[i]])
				printf("%d\n", i);
		printf("end\n");
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值