二分图判定+点染色/并查集 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 }
并查集做法

 

posted @ 2015-07-19 13:27  Running_Time  阅读(267)  评论(0编辑  收藏  举报