HDU 5973 Wrestling Match

本文探讨了一个比赛裁判面临的挑战,即如何通过已知的比赛结果和部分玩家的正邪身份,判断所有玩家的身份归属。利用并查集算法,文章提供了一种解决方案,确保比赛中的玩家能够被正确地划分为“好玩家”和“坏玩家”。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description:

Nowadays, at least one wrestling match is held every year in our country. There are a lot of people in the game is "good player”, the rest is "bad player”. Now, Xiao Ming is referee of the wrestling match and he has a list of the matches in his hand. At the same time, he knows some people are good players,some are bad players. He believes that every game is a battle between the good and the bad player. Now he wants to know whether all the people can be divided into "good player" and "bad player".

Input

Input contains multiple sets of data.For each set of data,there are four numbers in the first line:N (1 ≤ N≤ 1000)、M(1 ≤M ≤ 10000)、X,Y(X+Y≤N ),in order to show the number of players(numbered 1toN ),the number of matches,the number of known "good players" and the number of known "bad players".In the next M lines,Each line has two numbersa, b(a≠b) ,said there is a game between a and b .The next line has X different numbers.Each number is known as a "good player" number.The last line contains Y different numbers.Each number represents a known "bad player" number.Data guarantees there will not be a player number is a good player and also a bad player.

Output

If all the people can be divided into "good players" and "bad players”, output "YES", otherwise output "NO".

Sample Input

5 4 0 0
1 3
1 4
3 5
4 5
5 4 1 0
1 3
1 4
3 5
4 5
2

Sample Output

NO
YES

题目大意:

问能否通过题目给定的一些条件判断出N个人的身份(精确到每一个人)。

具体条件如下:M个关系,描述a,b身份不同。X个good身份的人和Y个bad身份的人并给出编号。

思路:

看完题立马想到上半年西安邀请赛热身的一道题,瞬间开始一顿胡写。。。 嗯WA了两发之后开始整理这道题的几个条件还是很好过的【据说是大连赛铜题。

核心是并查集没什么说的,用dfs也是可以的。注意点有几个, 对于已经确定关系的编号要注意他们的身份一定要是对立的。对于没有提及的人算不确定身份。对于已经确定身份【注意不是关系】的人要判断他们的关系是否符合他们的身份。数据量很小水水的写一下就好了。

代码:

#include <iostream>
#include <sstream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <utility>
#include <string>
#include <cmath>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int dir[9][2] = { 0, 1, 0, -1, 1, 0, -1, 0, 1, 1, 1, -1, -1, 1, -1, -1, 0, 0 };
const ll  ll_inf = 1e18;
const double PI=acos(-1.0);
const int inf = 0x3f3f3f;
const int mod = (int) 1e9 + 7;
const int Max = (int) 1e3+11;
const int N = (int) 40000+5;
const int maxn = (int) 120;
stringstream ss;

/**********************************************Head-----Template****************************************/
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
/**********************************************Head-----Temlate*****************************************/

//
// tools:
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(false);
//

int n ,m, x, y;
int rela[Max], Fa[Max];
vector < int> good, bad;
bool flag;
bool vis[Max];

void Init() {
	flag = true;
	for (int i = 1; i <= n; ++i) {
		// relative
		rela[i] = 0;
		Fa[i] = i;
	}
	while (!good.empty()) good.clear();
	while (!bad.empty()) bad.clear();
	memset(vis, false, sizeof(vis));
}

int Pa(int x) {
	if (x == Fa[x]) return x;
	int t = Fa[x];
	Fa[x] = Pa(Fa[x]);
	rela[x] = (rela[x] + rela[t]) % 2;
	return Fa[x];
}

bool Merge(int x, int y) {
	int fx = Pa(x);
	int fy = Pa(y);
	if (fx == fy) {
		if (rela[x] == rela[y])
			return false;
	}
	Fa[fx] = fy;
	rela[fx] = (rela[x] + rela[y] + 1) % 2;
	return true;
}

bool check() {
	if (good.size() && bad.size()) {
		for (int i = 0; i < good.size(); ++i) {
			for (int j = 0; j < bad.size(); ++j) {
				int x = good[i];
				int y = bad[j];
				vis[x] = vis[y] = true;
				int fx = Pa(x);
				int fy = Pa(y);
				if (fx == fy && rela[x] == rela[y]) return false;
			}
		}
	}
	if (good.size()) {
		for (int i = 0; i < good.size(); ++i) {
			for (int j = i; j < good.size(); ++j) {
				int x = good[i];
				int y = good[j];
				vis[x] = vis[y] = true;
				int fx = Pa(x);
				int fy = Pa(y);
				if (fx == fy && rela[x] != rela[y]) return false;
			}
		}
	}
	if (bad.size()) {
		for (int i = 0; i < bad.size(); ++i) {
			for (int j = i; j < bad.size(); ++j) {
				int x = bad[i];
				int y = bad[j];
				vis[x] = vis[y] = true;
				int fx = Pa(x);
				int fy = Pa(y);
				if (fx == fy && rela[x] != rela[y]) return false;
			}
		}
	}
	
	for (int i = 1; i <= n; ++i) {
		if (!vis[i]) return false;
	}
	
	return true;
}

int main() {
	
	while (~scanf("%d %d %d %d", &n, &m, &x, &y)) {
		Init();
		
		int a, b;
		while (m--) {
			scanf("%d %d", &a, &b);
			vis[a] = vis[b] = true;
			if (flag == false) {
				continue;
			}
			flag = Merge(a, b);			
		}
		
		int num;
		for (int i = 0; i < x; ++i) {
			scanf("%d", &num);
			good.push_back(num);
		}
		for (int i = 0; i < y; ++i) {
			scanf("%d", &num);
			bad.push_back(num);
		}
		
		if (flag) flag = check();	
		printf("%s\n", flag == true ? "YES" : "NO");
	}
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值