二分图判定+点染色/并查集 BestCoder Round #48 ($) 1002 wyh2000 and pupil
2015-07-19 13:27
381 查看
题目传送门
并查集做法
/* 二分图判定+点染色:因为有很多联通块,要对所有点二分图匹配,若不能,存在点是无法分配的,no 每一次二分图匹配时,将点多的集合加大最后第一个集合去 注意:n <= 1,no,两个集合都至少有一人;ans == n,扔一个给另一个集合 */ #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <vector> #include <map> using namespace std; const int MAXN = 1e5 + 10; const int INF = 0x3f3f3f3f; vector<int> G[MAXN]; int col[MAXN]; int cnt[3]; int n, m; bool DFS(int u) { for (int i=0; i<G[u].size (); ++i) { int v = G[u][i]; if (col[v] == -1) { col[v] = 3 - col[u]; cnt[col[v]]++; if (!DFS (v)) return false; } else if (col[v] == col[u]) return false; } return true; } void work(void) { memset (col, -1, sizeof (col)); int ans = 0; for (int i=1; i<=n; ++i) { if (col[i] == -1) { col[i] = 1; cnt[1] = 1; cnt[2] = 0; if (!DFS (i)) { puts ("Poor wyh"); return ; } ans += max (cnt[1], cnt[2]); } } if (ans == n) ans--; printf ("%d %d\n", ans, n - ans); } int main(void) //BestCoder Round #48 ($) 1002 wyh2000 and pupil { int t; scanf ("%d", &t); while (t--) { scanf ("%d%d", &n, &m); if (n <= 1) { puts ("Poor wyh"); continue; } for (int i=1; i<=n; ++i) G[i].clear (); for (int i=1; i<=m; ++i) { int u, v; scanf ("%d%d", &u, &v); G[u].push_back (v); G[v].push_back (u); } work (); } return 0; }
/* 并查集:有点像POJ食物链的做法, 分为(1, n)和(n+1, 2*n)两个集合,两种情况都试一下。 rt[i] == -1表示是该集合的根,用sz数组记录集合的大小 */ #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <vector> #include <map> using namespace std; const int MAXN = 1e5 + 10; const int INF = 0x3f3f3f3f; int n, m; struct UF { int rt[MAXN*2], sz[MAXN*2], sz2[MAXN*2]; void init(void) { memset (rt, -1, sizeof (rt)); for (int i=1; i<=2*n; ++i) sz[i] = (i <= n), sz2[i] = (i > n); } int Find(int x) { return rt[x] == -1 ? x : rt[x] = Find (rt[x]); } void Union(int x, int y) { x = Find (x); y = Find (y); if (x == y) return ; rt[x] = y; sz[y] += sz[x]; sz2[y] += sz2[x]; } bool same(int x, int y) { return Find (x) == Find (y); } }uf; int main(void) //BestCoder Round #48 ($) 1002 wyh2000 and pupil { int t; scanf ("%d", &t); while (t--) { scanf ("%d%d", &n, &m); bool ok = true; uf.init (); for (int i=1; i<=m; ++i) { int u, v; scanf ("%d%d", &u, &v); if (!ok) continue; if (uf.same (u, v) || uf.same (u+n, v+n)) ok = false; else uf.Union (u, v+n), uf.Union (u+n, v); } if (!ok || n <= 1) puts ("Poor wyh"); else if (m == 0) printf ("%d 1\n", n - 1); else { int ans = 0; for (int i=1; i<=n; ++i) { if (uf.rt[i] == -1) { ans += min (uf.sz[i], uf.sz2[i]); } } printf ("%d %d\n", n - ans, ans); } } return 0; }
并查集做法
相关文章推荐
- Apache Tomcat
- Leetcode 239 Sliding Window Maximum
- C++四种类型的转换
- openwrt 修改默认 IP
- read/write函数
- 带模除法
- C#继承
- Hdu 5285 wyh2000 and pupil (bfs染色判断奇环) (二分图匹配)
- 关于对char类型数据赋予负值的汇编表现
- 图文介绍MyEclipse (2015) 中创建简单的Maven项目的步骤(用于生成可执行jar文件)
- UITableViewQQ列表效果
- leetcode[20]:Valid Parentheses
- vim的学习
- 杭电ACM1124——Factorial
- 严重: An incompatible version 1.1.27 of the APR based&nb
- 2015年ALPC暑期专题练习I (计算几何) C
- [amanhardikar] - CodeReview
- 长连接 短连接 区别
- 图论题表
- (讨论)关于const修饰的值不能修改的实践