hdu 5971 Wrestling Match 二分图染色

题目链接

题意

(n)人进行(m)场比赛,给定(m)场比赛的双方编号;再给定已知的为(good player)(x)个人的编号,已知的为(bad player)(y)个人的编号。准则是每场比赛的两个选手必定一位来自(good player),另一位来自(bad player). 问是否可以据此将所有选手划分成两个阵营.

思路

// 题意和样例都很迷...

总的来说就是二分图染色,已经染好了若干个点,问能否顺利染成一个二分图。

但是不允许有孤立点。

具体操作上用(dfs)比较方便,因为图不连通,并查集不太好处理。

Code

#include <bits/stdc++.h>
#define maxn 2010
#define maxm 10010
bool flag;
int c[maxn], tot, ne[maxn], n, m, a, b, cnt;
struct Edge {
    int to, ne;
    Edge(int _to=0, int _ne=0): to(_to), ne(_ne) {}
}edge[maxm<<1];
void add(int u, int v) {
    edge[tot] = Edge(v, ne[u]);
    ne[u] = tot++;
}
using namespace std;
typedef long long LL;
void dfs(int u, int col) {
    ++cnt;
    if (flag) return;
    c[u] = col;
    for (int i = ne[u]; ~i; i = edge[i].ne) {
        int v = edge[i].to;
        if (c[v]==-1) dfs(v, !col);
        else if (c[v] == col) { flag = true; return; }
    }
}
void work() {
    int x, y;
    tot = 0; memset(ne, -1, sizeof(ne)); memset(c, -1, sizeof c);
    for (int i = 0; i < m; ++i) {
        scanf("%d%d", &x, &y);
        add(x, y), add(y, x);
    }
    for (int i = 0; i < a; ++i) scanf("%d", &x), c[x] = 0;
    for (int i = 0; i < b; ++i) scanf("%d", &x), c[x] = 1;
    flag = false;
    for (int i = 1; i <= n; ++i) {
        if (c[i] != -1) dfs(i, c[i]);
        if (flag) { printf("NO
"); return; }
    }
    for (int i = 1; i <= n; ++i) {
        if (c[i] == -1) cnt = 0, dfs(i, 0);
        if (flag || cnt == 1) { printf("NO
"); return; }
    }
    printf("YES
");
}
int main() {
    while (scanf("%d%d%d%d", &n, &m, &a, &b) != EOF) work();
    return 0;
}

原文地址:https://www.cnblogs.com/kkkkahlua/p/7668560.html