HDU 5313 Bipartite Graph(二分图 + bitset)
2015-07-31 20:50
369 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5313
题意:给一张无向图,问最多还能加多少条边使其变成变成边数最多的完全二分图
思路:还是先染色,然后对于每个联通分量能知道黑白各有多少个,当两边的点数越接近时,肯定总边数最多,故而可以dp,学了一下bitset的用法,看最终最接近(n + 1) / 2的且有值的那一位,即为最优解
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <string>
#include <bitset>
#include <ctime>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn = 10010;
const int inf = 0x3f3f3f3f;
int col[maxn];
int n, m;
vector <int> g[maxn];
int f1, f2, s1[maxn], s2[maxn];
bitset <maxn> dp;
void dfs(int u, int c)
{
col[u] = c;
col[u] == 1 ? f1++ : f2++;
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if (col[v] == -1)
dfs(v, 3 - c);
}
}
int solve()
{
if (n / 2 * (n - n / 2) == m) return 0;
dp.reset();
memset(col, -1, sizeof(col));
int tot = 0;
for (int i = 1; i <= n; i++)
{
if (col[i] == -1)
{
f1 = f2 = 0;
dfs(i, 1);
s1[tot] = f1;
s2[tot++] = f2;
}
}
dp[0] = 1;
for (int i = 0; i < tot; i++)
dp = dp << s1[i] | dp << s2[i];
for (int i = (n + 1) / 2; i >= 0; i--)
if (dp[i])
return i * (n - i) - m;
}
int main()
{
int t;
cin >> t;
while (t--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++)
g[i].clear();
for (int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
cout << solve() << endl;
}
return 0;
}
题意:给一张无向图,问最多还能加多少条边使其变成变成边数最多的完全二分图
思路:还是先染色,然后对于每个联通分量能知道黑白各有多少个,当两边的点数越接近时,肯定总边数最多,故而可以dp,学了一下bitset的用法,看最终最接近(n + 1) / 2的且有值的那一位,即为最优解
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <string>
#include <bitset>
#include <ctime>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn = 10010;
const int inf = 0x3f3f3f3f;
int col[maxn];
int n, m;
vector <int> g[maxn];
int f1, f2, s1[maxn], s2[maxn];
bitset <maxn> dp;
void dfs(int u, int c)
{
col[u] = c;
col[u] == 1 ? f1++ : f2++;
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if (col[v] == -1)
dfs(v, 3 - c);
}
}
int solve()
{
if (n / 2 * (n - n / 2) == m) return 0;
dp.reset();
memset(col, -1, sizeof(col));
int tot = 0;
for (int i = 1; i <= n; i++)
{
if (col[i] == -1)
{
f1 = f2 = 0;
dfs(i, 1);
s1[tot] = f1;
s2[tot++] = f2;
}
}
dp[0] = 1;
for (int i = 0; i < tot; i++)
dp = dp << s1[i] | dp << s2[i];
for (int i = (n + 1) / 2; i >= 0; i--)
if (dp[i])
return i * (n - i) - m;
}
int main()
{
int t;
cin >> t;
while (t--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++)
g[i].clear();
for (int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
cout << solve() << endl;
}
return 0;
}
相关文章推荐
- hdoj 4421 Bit Magic 【2-sat 经典题目】
- Android API Guides 阅读笔记(9)----Bound Service
- 【软工】——软工视频总结
- Win7与Ubuntu双系统时卸载Ubuntu的方法
- 秦柯视频与文档资料-全集
- 黑马程序员--C语言——预处理命令
- HUAS Summer Trainning #3~L
- ios-应用管理 字典转模型
- MySQL使用mysqlimport命令导入文本文件
- Path Sum
- 黑马程序员--C语言——结构体和枚举类型
- Javascript高级程序设计读书笔记(第10章 DOM)
- 关于Table的误解
- ACM-ICPC比赛介绍及相关参考
- 机器学习算法之决策树算法
- iOS Quartz2D - 画线段
- Java大数应用
- ZOJ 2342 Roads 二分图匹配
- zoj 3421 Error Curves(三分)
- 解决 wine 32 位 在 64 ubuntu上安装的问题