题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5285

bc:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=609&pid=1002

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 1304    Accepted Submission(s): 418

Problem Description
Young theoretical computer scientist wyh2000 is teaching his pupils.
Wyh2000 has n pupils.Id of them are from 
 
Input
In the first line, there is an integer 100000
 
Output
For each case, output the answer.
 
Sample Input
2 8 5 3 4 5 6 1 2 5 8 3 5 5 4 2 3 4 5 3 4 2 4
 
Sample Output
5 3 Poor wyh
 

题解:

有解条件:每个连通分量都为二分图,且能够分为人数都大于1的两组。

先用黑白染色法来判断每个连通分量是否都为二分图,之后对每个联通分量,分成黑白两组后人数多的进第一组,人数少的进第二组。

这样贪心会有一个问题,第二个组的人数少于1,所以还要做一些调整。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 101010;
const int INF = 0x3f3f3f3f;

struct Edge {
    int v, ne;
    Edge(int v = 0, int ne = 0) :v(v), ne(ne) {};
}egs[maxn * 2];

int n, m;
int head[maxn], tot;
//vis[i]==-1:没访问过,==0:白色,==1:黑色
int vis[maxn];

void addEdge(int u, int v) {
    egs[tot] = Edge(v, head[u]);
    head[u] = tot++;
}

int vis2[maxn];
//统计该连通分量黑白两色的人数
void dfs2(int cur, int &cnt0, int &cnt1) {
    vis2[cur] = 1;
    if (vis[cur] == 0) cnt0++;
    else cnt1++;
    int p = head[cur];
    while (p != -1) {
        Edge &e = egs[p];
        if (!vis2[e.v]) {
            dfs2(e.v, cnt0, cnt1);
        }
        p = e.ne;
    }
}
//二染色判二分图
bool dfs(int cur) {
    int p = head[cur];
    while (p != -1) {
        Edge &e = egs[p];
        if (vis[e.v] == -1) {
            vis[e.v] = vis[cur] ^ 1;
            dfs(e.v);
        }
        else if (vis[e.v] == vis[cur]) {
            return false;
        }
        p = e.ne;
    }
    return true;
}

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
    memset(vis, -1, sizeof(vis));
    memset(vis2, 0, sizeof(vis2));
}

int main() {
    int tc;
    scanf("%d", &tc);
    while (tc--) {
        init();
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            u--, v--;
            addEdge(u, v);
            addEdge(v, u);
        }
        int ans = 0;
        int flag = 0, adj = INF;
        for (int i = 0; i < n; i++) {
            if (vis[i] == -1) {
                vis[i] = 0;
                if (!dfs(i)) {
                    flag = 1; break;
                }
                else {
                    int cnt0 = 0, cnt1 = 0;
                    dfs2(i, cnt0, cnt1);
                    ans += max(cnt0, cnt1);
                    if (abs(cnt0 - cnt1) > 0) {
                        adj = min(adj, abs(cnt0 - cnt1));
                    }
                }
            }
        }
        //调整
        if (adj == INF) adj = 0;
        if (n - ans < 1) { ans -= adj; }
        if (flag || n - ans<1 || ans<1) {
            printf("Poor wyh\n");
        }
        else {
            printf("%d %d\n", max(ans, n - ans), min(ans, n - ans));
        }
    }
    return 0;
}
View Code

 

相关文章:

  • 2021-11-02
  • 2021-10-17
  • 2022-12-23
  • 2022-12-23
  • 2021-10-07
  • 2021-06-12
  • 2021-06-25
  • 2022-03-08
猜你喜欢
  • 2022-12-23
  • 2021-05-07
  • 2022-01-21
  • 2022-12-23
  • 2021-11-26
  • 2021-06-21
相关资源
相似解决方案