Description:
有n个拳击选手,m场比赛,现在假设拳击手可以分为两类,"good"和“bad”,现在已经知道了X个"good"选手名单和Y个“bad”选手名单,现在断言每场比赛必然是一个"good"和“bad”选手打,问这个断言是否正确。
Input:
n,m,X,Y
m场比赛的双方编号以及X和Y个选手编号
Output:
YES or NO
Analysis:
这一题的图论背景是显然的,也不难想到若结论成立,这就是个二分图。用染色法,对每个连通量判断是否是二分图,若不是直接返回false,若染色过程中发现了同类选手打架还是返回false。另外样例给了提示,一个特殊情况是若某个连通分量是孤立点则要看他是否已经被定义了“good”or"bad", 若没定义也是返回false。剩下就是返回true了。
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<ctime>
#include<cstring>
#include<string>
#include<float.h>
#include<stack>
#include<unordered_map>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1<<30;
const int MOD = 1000000007;
const int maxn = 1005;
int n, m, X, Y;
vector<int> G[maxn];
int color[maxn];
int statue[maxn];
bool bipartite(int u) {
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if (color[v] == color[u])return false;
if (!color[v]) {
color[v] = 3 - color[u];
if (statue[v]&&statue[v] == statue[u])return false;
if (!bipartite(v))return false;
}
}
return true;
}
bool solve() {
memset(color, 0, sizeof(color));
for (int i = 1; i <= n; ++i)if (!color[i]) {
color[i] = 1;
if (!bipartite(i)) return false;
if (G[i].size()==0&& statue[i] == 0)return false;
}
return true;
}
int main()
{
//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
while (~scanf("%d%d%d%d", &n, &m, &X, &Y)) {
for (int i = 1; i <= n; ++i) {
G[i].clear();
}
memset(statue, 0, sizeof(statue));
_for(i, 0, m) {
int x, y; scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
_for(i, 0, X) { int x; scanf("%d", &x); statue[x] = 1; }
_for(i, 0, Y) { int y; scanf("%d", &y); statue[y] = 2; }
puts((solve() ? "YES" : "NO"));
}
return 0;
}