题目链接
题意:
给你n, m, x, y四个数,n代表编号,接下来m行,每行两个数a,b,二者PK,其中一方为好人将不会输,接下来x个好人和y个坏人;问是否能够将每个人划分成好人或者坏人。
思路:
二分图染色问题,注意读题;
在已知的好人坏人中第一遍DFS,在余下的图中未知的位置,分别填上好人坏人的条件下看看是否都矛盾;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
const int MAXN = 2e5 + 10;
int head[MAXN], res[MAXN], sta[MAXN];
int cnt = 0;
int n, m, X, Y;
struct node {
int to;
int next;
}edge[MAXN << 1];
void add_edge(int u, int v) {
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
bool dfs(int u, int s) {
//printf("# : %d %d\n", u, s);
if(sta[u] != -1 && sta[u] != s) return false;
if(sta[u] == s) return true;
sta[u] = s;
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(sta[v] == -1) dfs(v, 1 - s);
if(sta[v] != -1 && !dfs(v, 1- s)) return false;
//if(v != u) if(!dfs(v, 1 - s)) return false;
}
return true;
}
int main() {
while(scanf("%d %d %d %d", &n, &m, &X, &Y) != EOF) {
bool flag = true;
CLR(head, -1);
CLR(sta, -1);
CLR(res, 0);cnt = 0;
for(int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
int k;
for(int i = 0; i < X + Y; i++) {
scanf("%d", &k);
res[k] = 1;
if(!dfs(k, i < X ? 1 : 0)) flag = false;
}
for(int i = 1; i <= n; i++) {
if(sta[i] == -1) {
// printf("*%d\n", head[i]);
if(head[i] == -1 || (!dfs(i, 0) && !dfs(i, 1))){
flag = false;
break;
}
}
}
puts(flag ? "YES" : "NO");
}
return 0;
}