二分图判定+点染色/并查集 BestCoder Round #48 ($) 1002 wyh2000 and pupil

 

题目传送门

 1 /*  2  二分图判定+点染色:因为有很多联通块,要对所有点二分图匹配,若不能,存在点是无法分配的,no  3  每一次二分图匹配时,将点多的集合加大最后第一个集合去  4  注意:n <= 1,no,两个集合都至少有一人;ans == n,扔一个给另一个集合  5 */  6 #include <cstdio>  7 #include <algorithm>  8 #include <cstring>  9 #include <cmath> 10 #include <string> 11 #include <vector> 12 #include <map> 13 using namespace std; 14 15 const int MAXN = 1e5 + 10; 16 const int INF = 0x3f3f3f3f; 17 vector<int> G[MAXN]; 18 int col[MAXN]; 19 int cnt[3]; 20 int n, m; 21 22 bool DFS(int u) 23 { 24 for (int i=0; i<G[u].size (); ++i) 25  { 26 int v = G[u][i]; 27 if (col[v] == -1) { 28 col[v] = 3 - col[u]; cnt[col[v]]++; 29 if (!DFS (v)) return false; 30  } 31 else if (col[v] == col[u]) return false; 32  } 33 34 return true; 35 } 36 37 void work(void) 38 { 39 memset (col, -1, sizeof (col)); 40 int ans = 0; 41 for (int i=1; i<=n; ++i) 42  { 43 if (col[i] == -1) 44  { 45 col[i] = 1; cnt[1] = 1; cnt[2] = 0; 46 if (!DFS (i)) { 47 puts ("Poor wyh"); return ; 48  } 49 ans += max (cnt[1], cnt[2]); 50  } 51  } 52 if (ans == n) ans--; 53 printf ("%d %d\n", ans, n - ans); 54 } 55 56 int main(void) //BestCoder Round #48 ($) 1002 wyh2000 and pupil 57 { 58 int t; scanf ("%d", &t); 59 while (t--) 60  { 61 scanf ("%d%d", &n, &m); 62 if (n <= 1) { 63 puts ("Poor wyh"); continue; 64  } 65 for (int i=1; i<=n; ++i) G[i].clear (); 66 for (int i=1; i<=m; ++i) 67  { 68 int u, v; scanf ("%d%d", &u, &v); 69  G[u].push_back (v); G[v].push_back (u); 70  } 71  work (); 72  } 73 74 75 return 0; 76 }
 1 /*

 2  并查集:有点像POJ食物链的做法, 分为(1, n)和(n+1, 2*n)两个集合,两种情况都试一下。  3  rt[i] == -1表示是该集合的根,用sz数组记录集合的大小  4 */

 5 #include <cstdio>

 6 #include <algorithm>

 7 #include <cstring>

 8 #include <cmath>

 9 #include <string>

10 #include <vector>

11 #include <map>

12 using namespace std; 13 

14 const int MAXN = 1e5 + 10; 15 const int INF = 0x3f3f3f3f; 16 int n, m; 17 struct UF { 18     int rt[MAXN*2], sz[MAXN*2], sz2[MAXN*2]; 19     void init(void) { 20         memset (rt, -1, sizeof (rt)); 21         for (int i=1; i<=2*n; ++i)  sz[i] = (i <= n), sz2[i] = (i > n); 22  } 23     int Find(int x) { 24         return rt[x] == -1 ? x : rt[x] = Find (rt[x]); 25  } 26     void Union(int x, int y) { 27         x = Find (x);   y = Find (y); 28         if (x == y) return ; 29         rt[x] = y; 30         sz[y] += sz[x]; sz2[y] += sz2[x]; 31  } 32     bool same(int x, int y) { 33         return Find (x) == Find (y); 34  } 35 }uf; 36 

37 int main(void)      //BestCoder Round #48 ($) 1002 wyh2000 and pupil

38 { 39     int t;   scanf ("%d", &t); 40     while (t--) 41  { 42         scanf ("%d%d", &n, &m); 43         bool ok = true; uf.init (); 44         for (int i=1; i<=m; ++i) 45  { 46             int u, v;   scanf ("%d%d", &u, &v); 47             if (!ok)   continue; 48             if (uf.same (u, v) || uf.same (u+n, v+n))   ok = false; 49             else    uf.Union (u, v+n), uf.Union (u+n, v); 50  } 51 

52         if (!ok || n <= 1)    puts ("Poor wyh"); 53         else if (m == 0)    printf ("%d 1\n", n - 1); 54         else { 55             int ans = 0; 56             for (int i=1; i<=n; ++i) { 57                 if (uf.rt[i] == -1) { 58                     ans += min (uf.sz[i], uf.sz2[i]); 59  } 60  } 61             printf ("%d %d\n", n - ans, ans); 62  } 63  } 64 

65     return 0; 66 }
并查集做法

 

你可能感兴趣的:(round)