Problem Description
Soda has a bipartite graph with n vertices
and m undirected
edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges he can add.



Note: There must be at most one edge between any pair of vertices both in the new graph and old graph.
 
Input
There are multiple test cases. The first line of input contains an integer T (1≤T≤100),
indicating the number of test cases. For each test case:



The first line contains two integers n and m, (2≤n≤10000,0≤m≤100000).



Each of the next m lines
contains two integer u,v (1≤u,v≤n,v≠u) which
means there's an undirected edge between vertex u and
vertex v.



There's at most one edge between any pair of vertices. Most test cases are small.
 
Output
For each test case, output the maximum number of edges Soda can add.
 
Sample Input
2
4 2
1 2
2 3
4 4
1 2
1 4
2 3
3 4
 
Sample Output
2
0
 
Source
 
Recommend
hujie   |   We have carefully selected several similar problems for you:  

pid=5315" target="_blank" style="color:rgb(26,92,200); text-decoration:none">5315 5314 5312 5311 5310 

 

大致题意:

有n个点。m条边的二分图(可能不连通)。问最多还能加多少条边变成全然二分图

思路:

显然每一连通块,都染成两种颜色,最后要尽量使两种颜色总数同样解才最优

显然有两种决策。不是染白就是染黑,01背包

dp[i][val]表示前i个连通块能染成同一色点数<=val的最大值

显然dp[scc][all/2]是最优解

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<ll,ll> pii; const int N = 10000+100;
const int M = 100000+1000;
struct Edge{
int v,nxt;
Edge(int v = 0,int nxt = 0):v(v),nxt(nxt){}
}es[M*2];
int n,m;
int ecnt;
int head[N];
inline void add_edge(int u,int v){
es[ecnt] = Edge(v,head[u]);
head[u] = ecnt++;
es[ecnt] = Edge(u,head[v]);
head[v] = ecnt++;
}
int col[N];
int cnt[N][2];
int top;
int sum = 0;
void dfs(int u,int fa){
col[u] = !col[fa];
cnt[top][col[u]]++;
for(int i = head[u];~i;i = es[i].nxt){
int v = es[i].v;
if(v == fa || col[v] != -1) continue;
dfs(v,u);
}
}
void ini(){
REP(i,n) head[i] = col[i] = -1,cnt[i][0] = cnt[i][1] = 0;
col[0] = top = sum = ecnt = 0;
}
int dp[2][N];
int main(){ int T;
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
ini();
REP(i,m){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
for(int i = n; i>= 1;i--){
if(col[i] != -1) continue;
top++;
dfs(i,0);
if(cnt[top][0] == 0 || cnt[top][1] == 0) {
cnt[top][0] = cnt[top][1] = 0;
top--;
}
else {
sum += cnt[top][0],sum += cnt[top][1];
}
} int nd = n-sum;
for(int i = 0;i <= sum/2;i++) dp[0][i] = 0;
REP(i,top){
for(int j = 0; j <= sum/2; j++){
dp[i&1][j] = -1;
if(j-cnt[i][0] >= 0 && dp[(i-1)&1][j-cnt[i][0]] != -1) dp[i&1][j] = dp[(i-1)&1][j-cnt[i][0]]+cnt[i][0];
if(j-cnt[i][1] >= 0 && dp[(i-1)&1][j-cnt[i][1]] != -1) {
dp[i&1][j] = max(dp[(i-1)&1][j-cnt[i][1]]+cnt[i][1],dp[i&1][j]);
}
}
int minn,maxx = sum-dp[top&1][sum/2];
int t = min(nd,maxx-dp[top&1][sum/2]);
minn = dp[top&1][sum/2]+t;
nd -= t;
if(nd) minn += nd/2, maxx += nd/2 + (nd&1);
printf("%d\n",minn*maxx-m);
}
}

HDU 5313 Bipartite Graph(二分图染色+01背包水过)的更多相关文章

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

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

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

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

  3. HDU 5313 Bipartite Graph (二分图着色,dp)

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

  4. HDU 5313 Bipartite Graph

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

  5. POJ 1112 Team Them Up! 二分图判定+01背包

    题目链接: http://poj.org/problem?id=1112 Team Them Up! Time Limit: 1000MSMemory Limit: 10000K 问题描述 Your ...

  6. HDU 3639 Bone Collector II(01背包第K优解)

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  7. HDU 2126 Buy the souvenirs (01背包,输出方案数)

    题意:给出t组数据 每组数据给出n和m,n代表商品个数,m代表你所拥有的钱,然后给出n个商品的价值 问你所能买到的最大件数,和对应的方案数.思路: 如果将物品的价格看做容量,将它的件数1看做价值的话, ...

  8. HDU 1203 I NEED A OFFER! 01背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1203 解题思路:简单的01背包,用dp[i]表示花费不超过i时的最大可能性 状态转移方程 dp[i]= ...

  9. HDU 2639 Bone Collector II【01背包 + 第K大价值】

    The title of this problem is familiar,isn't it?yeah,if you had took part in the "Rookie Cup&quo ...

随机推荐

  1. APUE 学习笔记(七) 信号

    1.信号是软件中断,提供一种异步处理事件的方法 很多事件产生信号: (1)用户按下某些中断键,如 Ctrl + C键产生 SIGINT信号 (2)硬件异常产生信号,比如 除数为0,无效的内存引用  ( ...

  2. 用jquery写的position瀑布流布局

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 用node写的一个后台框架

    server.js var http=require('http') var handleUrl=require('./handleUrl') var config = require('./conf ...

  4. 转 new和malloc的区别

    传送门 new和malloc的区别 1. malloc()函数 1.1 malloc的全称是memory allocation,中文叫动态内存分配. 原型:extern void *malloc(un ...

  5. 使用Naive Bayes从个人广告中获取区域倾向

    RSS源介绍:https://zhidao.baidu.com/question/2051890587299176627.html http://www.rssboard.org/rss-profil ...

  6. 2016-2017 ACM-ICPC, South Pacific Regional Contest (SPPC 16)

    题目链接  Codeforces_Gym_101177 Problem A  Anticlockwise Motion 直接模拟即可 #include<iostream> #include ...

  7. 浅析 JavaScript 中的闭包(-------------------------------------------)

    一.前言 对于 JavaScript 来说,闭包是一个非常强大的特征.但对于刚开始接触的初学者来说它又似乎是特别高深的.今天我们一起来揭开闭包的神秘面纱.闭包这一块也有很多的文章介绍过了,今天我就浅谈 ...

  8. 启动weblogic域不需要输入密码设置方法

    分类: IT综合技术 一.问题描述与分析     部署完WEBLOGIC后,在每次启动时执行./startWebLogic.sh脚本时,都会停在输入用户名与密码这里,相当不方便.所以要做到启动过程不输 ...

  9. win10安装 迅雷

    下载安装文件所在目录 ,右键,选择以管理员身份运行,输入程序地址,如D:\download\ThunderMini_dl1.5.3.288.exe,回车,这样就出来了程序安装页面,之后就可以就行正常的 ...

  10. 【转载】Spark学习——入门

    要学习分布式以及数据分析.机器学习之类的,觉得可以通过一些实际的编码项目入手.最近Spark很火,也有不少招聘需要Spark,而且与传统的Hadoop相比,Spark貌似有一些优势.所以就以Spark ...