二分图点染色 BestCoder 1st Anniversary($) 1004 Bipartite Graph
2015-07-26 10:02
330 查看
题目传送门
/* 二分图点染色:这题就是将点分成两个集合就可以了,点染色用dfs做, 剩下的点放到点少的集合里去 官方解答:首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|*|Y|.我们的目的是max{|X|*|Y|}, 并且|X|+|Y|=n. 修正:实现多连通块染色,然后贪心选择,将两个集合个数差大的连通块优先添加,能尽量使得un*vn最大 */ #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <map> using namespace std; const int MAXN = 1e4 + 10; const int MAXM = 1e5 + 10; const int INF = 0x3f3f3f3f; vector<int> G[MAXN]; int col[2*MAXN]; bool vis[MAXN]; struct Block { //连通块 int u, v; bool operator < (const Block &r) const { return u - v > r.u - r.v; } }b[MAXN]; int n, m, un, vn; void DFS(int u, int c) { col[c]++; vis[u] = true; for (int i=0; i<G[u].size (); ++i) { int v = G[u][i]; if (vis[v]) continue; DFS (v, c ^ 1); } } int main(void) { //BestCoder 1st Anniversary($) 1004 Bipartite Graph //freopen ("D.in", "r", stdin); int T; scanf ("%d", &T); while (T--) { scanf ("%d%d", &n, &m); for (int i=1; i<=n; ++i) G[i].clear (); for (int i=1; i<=m; ++i) { int u, v; scanf ("%d%d", &u, &v); G[u].push_back (v); G[v].push_back (u); } int color = 0; memset (vis, false, sizeof (vis)); memset (col, 0, sizeof (col)); for (int i=1; i<=n; ++i) { if (vis[i]) continue; DFS (i, color); color += 2; } int cnt = 0; for (int i=0; i<color; i+=2) { b[++cnt].u = col[i]; b[cnt].v = col[i^1]; if (b[cnt].u < b[cnt].v) swap (b[cnt].u, b[cnt].v); } sort (b+1, b+1+cnt); un = vn = 0; for (int i=1; i<=cnt; ++i) { if (un <= vn) { un += b[i].u; vn += b[i].v; } else { un += b[i].v; vn += b[i].u; } } printf ("%d\n", un * vn - m); } return 0; }
相关文章推荐
- Apache支持 shtml和include文件解析
- Bipartite Graph
- Mac Os 基本命令行
- JavaScript学习笔记——数据类型强制转换和隐式转换
- 秋田中文离线地图App上线
- Compass简单介绍
- Java枚举类学习笔记和设置不可变类
- 并查集树数据结构hdu1325
- 创建分和生日比较数组
- 在浏览器的地址栏位置, 使用javascript:输入一个表达式来测试.
- ArcGIS中数据之间的转换接口IFeatureDataConverter2
- BZOJ 4195 NOI 2015 Day1 T1 程序自动分析
- Ubuntu 14.04 安装 Altera DS-5
- 深入理解依赖注入
- count()与sum()
- 基础最短路(模板 bellman_ford)
- Android开发笔记-----activity简述
- 虚拟机下centos6的网络IP配置
- smarty逻辑运算符
- 横滨中文离线地图App上线