• 二分图点染色 BestCoder 1st Anniversary($) 1004 Bipartite Graph


    题目传送门

     1 /*
     2   二分图点染色:这题就是将点分成两个集合就可以了,点染色用dfs做, 剩下的点放到点少的集合里去
     3     官方解答:首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|*|Y|.我们的目的是max{|X|*|Y|}, 并且|X|+|Y|=n.
     4     修正:实现多连通块染色,然后贪心选择,将两个集合个数差大的连通块优先添加,能尽量使得un*vn最大
     5  */
     6 #include <cstdio>
     7 #include <algorithm>
     8 #include <cstring>
     9 #include <vector>
    10 #include <map>
    11 using namespace std;
    12 
    13 const int MAXN = 1e4 + 10;
    14 const int MAXM = 1e5 + 10;
    15 const int INF = 0x3f3f3f3f;
    16 vector<int> G[MAXN];
    17 int col[2*MAXN];
    18 bool vis[MAXN];
    19 struct Block    {       //连通块
    20     int u, v;
    21     bool operator < (const Block &r) const  {
    22         return u - v > r.u - r.v;
    23     }
    24 }b[MAXN];
    25 int n, m, un, vn;
    26 
    27 void DFS(int u, int c)    {
    28     col[c]++; vis[u] = true;
    29     for (int i=0; i<G[u].size (); ++i)  {
    30         int v = G[u][i];
    31         if (vis[v]) continue;
    32         DFS (v, c ^ 1);
    33     }
    34 }
    35 
    36 int main(void)  {       //BestCoder 1st Anniversary($) 1004 Bipartite Graph
    37     //freopen ("D.in", "r", stdin);
    38 
    39     int T;  scanf ("%d", &T);
    40     while (T--) {
    41         scanf ("%d%d", &n, &m);
    42         for (int i=1; i<=n; ++i)    G[i].clear ();
    43         for (int i=1; i<=m; ++i)    {
    44             int u, v;   scanf ("%d%d", &u, &v);
    45             G[u].push_back (v); G[v].push_back (u);
    46         }
    47 
    48         int color = 0;
    49         memset (vis, false, sizeof (vis));
    50         memset (col, 0, sizeof (col));
    51         for (int i=1; i<=n; ++i)    {
    52             if (vis[i]) continue;
    53             DFS (i, color);    color += 2;
    54         }
    55         int cnt = 0;
    56         for (int i=0; i<color; i+=2) {
    57             b[++cnt].u = col[i];  b[cnt].v = col[i^1];
    58             if (b[cnt].u < b[cnt].v)    swap (b[cnt].u, b[cnt].v);
    59         }
    60         sort (b+1, b+1+cnt);
    61 
    62         un = vn = 0;
    63         for (int i=1; i<=cnt; ++i)  {
    64             if (un <= vn)   {
    65                 un += b[i].u;   vn += b[i].v;
    66             }
    67             else    {
    68                 un += b[i].v;   vn += b[i].u;
    69             }
    70         }
    71         printf ("%d
    ", un * vn - m);
    72     }
    73 
    74     return 0;
    75 }
    编译人生,运行世界!
  • 相关阅读:
    链表面试题(一):反转链表的算法实现
    Flutter随笔(二)——使用Flutter Web + Docker + Nginx打造一个简单的Web项目
    Spring MVC知识要点
    ddd
    可编辑下拉框(ie6/chrome)
    Ajax+PHP简单实例
    移动app嵌套h5页面meta标签
    为什么python适合写爬虫?(python到底有啥好的?!)
    自学java第一天(写第一个程序)
    git桌面工具
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4677177.html
Copyright © 2020-2023  润新知