题意:

  Soda有一个n个点m条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的.

思路:

  先将二分图着色,将每个连通分量区分出左右两边的点,在着色过程中,顺便将每个连通分量两边的点数存起来,注意一个连通分量左右两边的点数是绑定的一对数字。现在的问题就是,需要将这几对数字给分配掉,每一对都必须拆开来丢到不同的桶中,而且尽量使得两桶中各自的数字之和最接近,才能使得边最多。

  分配的过程可以使用DP解决,主要是数字挺大的,bitset优化的背包很强大,可以解决这个问题。

bitset优化了的代码:

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
vector<int> vect[N];
int col[N], set1, set2; void color(int u, int c)
{
col[u]=c;
col[u]==?set2++:set1++;//统计两边的数量
for(int i=; i<vect[u].size(); i++)
{
int t=vect[u][i];
if(!col[t]) color(t, -col[u] );
}
} bitset<N> dp;
int s1[N/], s2[N/];
int cal(int n, int m)
{
if(m==n/*(n-n/) ) return ;
dp.reset(); memset(col, , sizeof(col));
int ans=, k=;
for(int i=; i<=n; i++)
{
if(!col[i])
{
set1=set2=;
color(i, ); s1[k]=set1;//每个连通分量两边的点数
s2[k++]=set2;
}
} dp[]=;
for(int i=; i<k; i++) //类似于背包+bitset优化
dp = dp<<s1[i] | dp<<s2[i]; //这么神奇!! for(int i=n/; i>=; i--) //再将那个最接近n/2的找出来即可
if( dp[i] ) return i*(n-i)-m;
} int main()
{
freopen("input.txt", "r", stdin);
int n, m, t, p, q, a, b;
cin>>t; while(t--)
{
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++) vect[i].clear();
for(int i=; i<m; i++)
{
scanf("%d%d",&a,&b);
vect[a].push_back(b);
vect[b].push_back(a);
}
printf("%d\n",cal(n, m));
}
return ;
}

AC代码

贴一个没有优化的TLE代码:

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
vector<int> vect[N];
int col[N];
int set1, set2; void color(int u, int c)
{
col[u]=c;
if(col[u]==) set1++;//统计两边的数量
else set2++; for(int i=; i<vect[u].size(); i++)
{
int t=vect[u][i];
if(!col[t]) //没色
color(t, -col[u] );
}
} bitset<N/> dp[N];
int s1[N/],s2[N/];
int cal(int n, int m)
{
if(m==n/*(n-n/) ) return ;
for(int i=; i<=n; i++) vect[i].clear(), dp[i].reset(); memset(col, , sizeof(col));
int ans=, k=;
for(int i=; i<=n; i++)
{
if(!col[i])
{
set1=set2=;
color(i, ); s1[k]=set1;//每个连通分量两边的点数
s2[k++]=set2;
}
} if(k==) return s1[] * s2[] - m;//连通图
dp[][]=;
for(int i=; i<k; i++)//在这进行DP,尽量使得两边的点数平衡
{
ans=;
set1=s1[i];
set2=s2[i]; for(int j=n/; j>=set1; j--)
if( dp[i][j-set1] ) dp[i+][j]=,ans=max(ans,j); for(int j=n/; j>=set2; j--)
if( dp[i][j-set2] ) dp[i+][j]=,ans=max(ans,j);
}
return ans*(n-ans)-m;
} int main()
{
//freopen("input.txt", "r", stdin);
int n, m, t, p, q, a, b;
cin>>t; while(t--)
{
scanf("%d%d",&n,&m);
for(int i=; i<m; i++)
{
scanf("%d%d",&a,&b);
vect[a].push_back(b);
vect[b].push_back(a);
}
printf("%d\n",cal(n, m));
}
return ;
}

TLE代码

HDU 5313 Bipartite Graph (二分图着色,dp)的更多相关文章

  1. HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】

    Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  2. HDU 5313 Bipartite Graph(二分图染色+01背包水过)

    Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants ...

  3. hdu 5313 Bipartite Graph(dfs染色 或者 并查集)

    Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants ...

  4. HDU 5313 Bipartite Graph

    题意:给一个二分图,问想让二分图变成完全二分图最多能加多少条边. 解法:图染色+dp+bitset优化.设最终的完全二分图两部分点集为A和B,A中点个数为x,B中点个数为y,边数则为x × y,答案即 ...

  5. bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5006 https://www.luogu.org/problemnew/show/P4547 ...

  6. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

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

    题目传送门 /* 二分图点染色:这题就是将点分成两个集合就可以了,点染色用dfs做, 剩下的点放到点少的集合里去 官方解答:首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|*|Y|.我们的 ...

  8. HDU 5285 wyh2000 and pupil (二分图着色)

    题意: 共有n个小学生,编号为1−n.将所有小学生分成2组,每组都至少有1个人.但是有些小学生之间并不认识,而且如果a不认识b,那么b也不认识a.Wyh2000希望每组中的小学生都互相认识.而且第一组 ...

  9. HDU 6321 Dynamic Graph Matching

    HDU 6321 Dynamic Graph Matching (状压DP) Problem C. Dynamic Graph Matching Time Limit: 8000/4000 MS (J ...

随机推荐

  1. Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 奇环

    题目链接: 点这里 题目 D. Vitaly and Cycle time limit per test1 second memory limit per test256 megabytes inpu ...

  2. firefox同步ajax请求报错的问题 A parameter or an operation is not supported by the underlying object

    今天在测试系统时,一个很正常的功能在firefox下报错,经过验证在ie和chrome浏览器中功能这个正常.   调试后发现: 请求比其他请求的特殊点在于同步请求.   经过firefox的控制台上测 ...

  3. myeclipse一直bulid workspace 的解决

    解决方法转自: http://zhidao.baidu.com/link?url=gCj0XzorUUshtSFG2jXh6-Bxn28_LpcbTYasbgk9Qja_kw8Ex2kLzxFSYHN ...

  4. Eclipse插件开发 swt ComboBoxCellEditor CCombo 下拉框高度

    效果图:     代码如下 bindingPageTableViewer.setCellModifier(new ICellModifier() { public boolean canModify( ...

  5. HTML5 动画引擎 小记

    国内: Cocos2d-x js版本   layabox Egret Sirius2D lufylegend.js Fireball 国外: CreateJS(EaselJS.TweenJS)http ...

  6. 灵魂有香气的女子IOS版本APP,近期将考虑开放源代码

    实在太忙,灵魂有香气的女子这个App,断断续续开发了1个多月了,前后台自己独立完成, 由于接触swift没多久,还属于新手行列,不熟悉,希望大家给出意见, 根据意见,完善后将于近期将考虑开放swift ...

  7. linux源代码阅读笔记 fork和execve的区别

    1. man exec就可以知到: The exec() family of functions replaces the current process image with a new proce ...

  8. orale内置函数COALESCE和GREATEST和LEAST

    1. COALESCE 返回该表达式列表的第一个非空value. 格式: COALESCE(value1, value2, value3, ...) 含义: 返回value列表第一个非空的值. val ...

  9. cojs 简单的01串 题解报告

    题意显然是求n位二进制串中不大于其逆序串,取反串,逆序取反串的所有串按字典序排序后的第k个 由于n很小,k很大所以我们可以考虑逐位确定 问题转化为了求方案数,这显然是可以用数位DP做的 设f[len] ...

  10. 再谈PCA

        其实之前写过PCA相关的博文,但是由于之前掌握的理论知识有限,所以理解也比较浅.这篇博文,我们以另外一种角度来理解PCA看,这里我假设大家对PCA都有一个初步的了解.首先,我们举一个二维空间中 ...