zoukankan      html  css  js  c++  java
  • Bipartite Graph hdu 5313 bitset 并查集 二分图

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5313

    题意:

    给出n个顶点,m条边,问最多添加多少条边使之构成一个完全二分图

    存储结构:

    bitset     【用法详情:http://blog.csdn.net/piaocoder/article/details/47177891】

    用时:624ms

    思路:

    二分图的总边数即:n*m(假设一个有n个点,另一个有m个点)

    题目是给出总共的点数为n,间接求最大的边数

    想到一个小学题:给出长度为n的绳子,将其分为两截,使以这两截长度作为长和宽的矩形面积最大,当然,就是平分喽

    虽然,此题不一定和小学题一模一样,但是要想使得分出的n和m乘积最大,必须使n和m尽可能相近,没问题吧。

    然后我们用一个并查集先分出各个连通图,再做相应的处理即可,详见注释

    代码如下:    

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<bitset>
     5 using namespace std;
     6 const int v_N = 10010;  //总结点数
     7 bitset<v_N> Bit;      //允许多少条边构成一个集合,比如:允许一个点构成一个集合,那么Bit[1]为真,否则为假
     8 int n, m, group, fa[v_N], color[v_N], part_num[v_N][2];
     9 //fa:父亲; color:染色  part_num:同一个集合(并查集得到)中各个颜色所拥有的结点个数
    10 int find(int x)
    11 {
    12     if (x == fa[x])
    13         return x;
    14     int t = fa[x];
    15     fa[x] = find(fa[x]);
    16     color[x] ^= color[t];          //当前与父亲异或,刷新颜色  
    17     return fa[x];
    18 }
    19 void solve()
    20 {
    21     for (int i = 1; i <= n; ++i)
    22         Bit[i] = 0;
    23     Bit[0] = 1;
    24     for (int i = 1; i <= n; ++i)  //统计
    25         part_num[find(i)][color[i]]++;
    26     for (int i = 1; i <= n; ++i)
    27         if (i == fa[i])           //说明一个集合结束了,刷新Bit
    28             Bit = (Bit << part_num[i][0]) | (Bit << part_num[i][1]);
    29     int _max = 0;
    30     for (int i = n / 2 - 1; i <= n / 2 + 1; ++i)  //遍历半数左右即可!!  剪枝
    31         if (Bit[i])
    32             _max = max(_max, i*(n - i) - m);
    33     printf("%d
    ", _max);
    34 }
    35 
    36 int main()
    37 {
    38     scanf("%d", &group);
    39     while (group--)
    40     {
    41         scanf("%d%d", &n, &m);
    42         for (int i = 1; i <= n; ++i)
    43             fa[i] = i, color[i] = part_num[i][0] =  part_num[i][1] = 0;
    44         for (int i = 0; i < m; ++i)
    45         {
    46             int x, y, fx, fy;
    47             scanf("%d%d", &x, &y);
    48             fx = find(x), fy = find(y);
    49             if (fx == fy)
    50                 continue;
    51             fa[fx] = fy; 
    52             color[fx] = 1 ^ color[x] ^ color[y];  //保证同一条边或不同一集合颜色不同,初始为0,所以用1异或
    53         }
    54         solve();
    55     }
    56 }

    感谢您的阅读,生活愉快~

  • 相关阅读:
    创作型---简单工厂模式
    创作型---建造者模式
    创作型---原型模式(C# ICloneable接口的实现)
    创作型---单例模式
    实时数据库简介和比较---PI
    记一次项目启动卡死不动,控制台无错误信息
    记一次jdk1.7升级jdk1.8项目报错
    javamail插件发送不同类型邮件方式
    javaweb购物车实现的几种方式
    android客户端app和服务端交互token的作用
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/8471713.html
Copyright © 2011-2022 走看看