zoukankan      html  css  js  c++  java
  • 二分图判定+点染色/并查集 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
    ", 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 - 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 - ans, ans);
    62         }
    63     }
    64 
    65     return 0;
    66 }
    并查集做法
    编译人生,运行世界!
  • 相关阅读:
    Java线程池之ThreadPoolExecutor
    React Native开发环境的搭建
    Android Lint——内嵌于Android Studio的代码优化工具
    Android异步处理技术
    NavigationView的头部的事件监听
    进程间通信之AIDL
    跨进程通信之Messenger
    Android 进程增加存活率
    android MVP模式思考
    Vim学习
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4658530.html
Copyright © 2011-2022 走看看