您的位置:首页 > 其它

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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: