zoukankan      html  css  js  c++  java
  • Hdu 5285 wyh2000 and pupil (bfs染色判断奇环) (二分图匹配)

    题目链接:

      BestCoder Round #48 ($) 1002

    题目描述:

      n个小朋友要被分成两班,但是有些小朋友之间是不认得的,所以规定不能把不认识的小朋友分在一个班级里面,并且一班的人数要比二班的人数多,每个班的人数都大于零。

    解题思路:

      hdu给出的题解是二分图匹配加上贪心,就不多说了。

      还可以用bfs对节点染色,建好图后,对节点进行bfs分成,偶数成与奇数成染成不同的颜色,颜色相同的节点都可以分到同一个集合里面,但是要判断一下奇环,如果出现奇环的话,是无法进行分组的。在每次bfs的时候再加上贪心累计求和。

     1 #include <queue>
     2 #include <vector>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <algorithm>
     7 using namespace std;
     8 const int maxn = 100010;
     9 vector < int > G[maxn];
    10 
    11 int x, y, n, m, vis[maxn], flag;
    12 void bfs (int s)
    13 {
    14     int p, q, zreo, one, num;
    15     queue <int> Q;
    16     zreo = 1;
    17     one = vis[s] = 0;
    18     Q.push(s);
    19     while (!Q.empty())
    20     {
    21         p = Q.front();
    22         Q.pop();
    23         num = (vis[p] + 1) % 2;
    24         for (int i=0; i<G[p].size(); i++)
    25         {
    26             q = G[p][i];
    27             if (vis[q]!=-1 && num != vis[q])
    28                 flag = 1;
    29             if (vis[q]==-1)
    30             {
    31                 Q.push(q);
    32                 vis[q] = num;
    33                 if (num == 0)
    34                     zreo ++;
    35                 else
    36                     one ++;
    37             }
    38         }
    39     }
    40     x += max (zreo, one);
    41     y += min (one, zreo);
    42 }
    43 int main ()
    44 {
    45     int t;
    46     scanf ("%d", &t);
    47     while (t --)
    48     {
    49         scanf ("%d %d", &n, &m);
    50         memset (vis, -1, sizeof(vis));
    51         for (int i=0; i<=n; i++)
    52             G[i].clear();
    53         x = y = flag = 0;
    54         while (m --)
    55         {
    56             int a, b;
    57             scanf ("%d %d", &a, &b);
    58             G[a].push_back (b);
    59             G[b].push_back (a);
    60         }
    61         for (int i=1; i<=n; i++)
    62         {
    63             if (vis[i] == -1)
    64                 bfs (i);
    65             if (flag)
    66                 break;
    67         }
    68         if (x == n)
    69         {
    70             x --;
    71             y ++;
    72         }
    73         if (flag || x < 1 || y < 1)
    74             printf ("Poor wyh
    ");
    75         else
    76             printf ("%d %d
    ", x, y);
    77     }
    78     return 0;
    79 }

    用二分图匹配要比bfs快一半,内存也要少好多,所以再贴一个二分图匹配的代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 using namespace std;
     6 const int maxn = 100010;
     7 struct Edge
     8 {
     9     int to, next;
    10 }edge[2*maxn];
    11 int tot, head[maxn], vis[maxn];
    12 
    13 void init ()
    14 {
    15     tot = 0;
    16     memset (head, -1, sizeof(head));
    17 }
    18 void Add (int from, int to)
    19 {
    20     edge[tot].to = to;
    21     edge[tot].next = head[from];
    22     head[from] = tot ++;
    23 }
    24 bool dfs (int x, int c, int &a, int &b)
    25 {
    26     b ++;
    27     if (c)
    28         a ++;
    29     vis[x] = c;
    30     for (int i=head[x]; i!=-1; i=edge[i].next)
    31     {
    32         int num = edge[i].to;
    33         if (vis[num] == c)
    34             return false;
    35         if (vis[num] == -1 && !dfs(num, c^1, a, b))
    36             return false;
    37     }
    38     return true;
    39 }
    40 int main ()
    41 {
    42     int t, n, m;
    43     scanf ("%d", &t);
    44     while (t --)
    45     {
    46         scanf ("%d %d", &n, &m);
    47         init ();
    48         while (m --)
    49         {
    50             int a, b;
    51             scanf ("%d %d", &a, &b);
    52             Add (a, b);
    53             Add (b, a);
    54         }
    55         int x, y;
    56         bool flag = true;
    57         memset (vis, -1, sizeof(vis));
    58         x = y = 0;
    59         for (int i=1; i<=n; i++)
    60         {
    61             int a, b;
    62             a = b = 0;
    63             if (vis[i] == -1)
    64             {
    65                 if (!dfs (i, 0, a, b))
    66                 {
    67                     flag = false;
    68                     break;
    69                 }
    70             }
    71             x += max (a, b - a);
    72             y += min (a, b - a);
    73         }
    74         if (x == n)
    75         {
    76             x --;
    77             y ++;
    78         }
    79         if (!flag || x<1 || y<1)
    80             printf ("Poor wyh
    ");
    81         else
    82             printf ("%d %d
    ", x, y);
    83     }
    84     return 0;
    85 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    php数据库常用函数
    什么是RESTful API
    RESTful API 设计指南
    json和jsonp的使用区别
    Memcached, Redis, MongoDB区别
    入门系列之在Nginx配置Gzip
    100行代码搞定抖音短视频App,终于可以和美女合唱了。
    游戏开发者注意!这个音频SDK可以完美兼容所有主流游戏引擎
    快速上手:在CVM上安装Apache
    聚焦小游戏技术生态,腾讯游戏云GAME-TECH落地厦门
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4658527.html
Copyright © 2011-2022 走看看