题目链接:
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
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; }