二分图点染色 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\n", un * vn - m);
72     }
73 
74     return 0;
75 }

 

posted @ 2015-07-26 10:02  Running_Time  阅读(329)  评论(4编辑  收藏  举报