记录编号 593661 评测结果 A
题目名称 [POJ 1417]真正的说谎者 最终得分 100
用户昵称 Gravatar健康铀 是否通过 通过
代码语言 C++ 运行时间 0.014 s
提交时间 2024-09-06 22:04:13 内存使用 7.49 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int maxn = 1005;
set<int>st;
int s[maxn];
int r[maxn];
int f[maxn];
int dp[maxn][maxn];
int a[maxn][2];
inline void clear_set()
{
	st.clear();
	for(int i = 0;i < maxn;i++){
		s[i] = i;
	}
	memset(r,0,sizeof(r));
	memset(f,0,sizeof(f));
	memset(a,0,sizeof(a));
	memset(dp,0,sizeof(dp));
}
int find_set(int x)
{
	if(x != s[x]){
		int f = s[x];
		s[x] = find_set(s[x]);
		r[x] = (r[x]+r[f])%2;
	}
	return s[x];
}
inline void union_set(int x,int y,int z)
{
	int fx = find_set(x);
	int fy = find_set(y);
	if(fx != fy){
		s[fy] = fx;
		r[fy] = (r[x]-r[y]+z+2)%2;
	}	
}
int main()
{
        freopen("trueliars.in","r",stdin);
    freopen("trueliars.out","w",stdout);
	int n,p,q;
	while(cin >> n >> p >> q && (n | p | q)){
		int m = p+q;
		clear_set();
		for(int i = 0;i < n;i++){
			char str[5];
			int x,y,z = 0;					
			scanf("%d%d%s",&x,&y,str);
			if(str[0] == 'n')	z = 1;			
			union_set(x,y,z);
		} 
		int tot = 0;
		for(int i = 1;i <= m;i++){
			if(find_set(i) == i){
				f[++tot] = i;					
				for(int j = 1;j <= m;j++){
					if(find_set(j) == i){
						a[tot][r[j]]++;		 
					}
				}
			}
		}
		dp[0][0] = 1;
		for(int i = 1;i <= tot;i++){			
			for(int j = p;j >= 0;j--){	
			     if(j >= a[i][0])
				dp[i][j] += dp[i-1][j-a[i][0]];	
				if(j >= a[i][1])
                dp[i][j] += dp[i-1][j-a[i][1]];	 
			}
				
		}
		if(dp[tot][p] != 1){
			printf("no\n");
			continue;
		}
		int t = p;
		for(int i = tot;i >= 1;i--){
			if(dp[i-1][t-a[i][0]] == 1){
				for(int j = 1;j <= p+q;j++){
					if(find_set(j) == f[i] && r[j] == 0){
						st.insert(j);
					}
				}
				t -= a[i][0]; 
			}
			else{
				for(int j = 1;j <= p+q;j++){
					if(find_set(j) == f[i] && r[j] == 1){
						st.insert(j);
					}
				}
				t -= a[i][1];
			}
		}
		set<int>::iterator ptr;
		for(ptr = st.begin();ptr != st.end();ptr++){
			printf("%d\n",*ptr);
		}
		printf("end\n");
	}
	return 0;
}