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. wamp出现You don’t have permission to access/on this server提示

    本地搭建wamp,输入http://127.0.0.1访问正常,当输入http://localhost/,apache出现You don't have permission to access/on ...

  2. A* k短路 学习笔记

    题目大意 n个点,m条边有向图,给定S,T,求不严格k短路 n<=1000 m<=100000 k<=1000 不用LL 分析 A*算法 f(i)表示从S出发经过i到T的估价函数 \ ...

  3. 【HDOJ6218】Bridge(线段树,set,网格图,连通性)

    题意:给定一张2×n的网格图,一开始矩阵所有相邻点之间有一条边 有q个询问,每次给出两个相邻的点的坐标,将其中的边删除或者添加,问如此操作之后整张图的割边数量     n,q<=2*10^5, ...

  4. 转 如何在C++中调用C程序

    如何在C++中调用C程序?   C++和C是两种完全不同的编译链接处理方式,如果直接在C++里面调用C函数,会找不到函数体,报链接错误.要解决这个问题,就要在 C++文件里面显示声明一下哪些函数是C写 ...

  5. linux 时间模块 二

    Linux中有硬件时钟与系统时钟 在Linux中有硬件时钟与系统时钟等两种时钟.硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟.系统时钟则是指kernel中的时钟.当Linux启 ...

  6. Visual Studio Code 使用教程

    visual studio code以下简称vsc.vsc这个编辑器也火了一会了,最近在跟风学一波typescript,网络上很多人说vsc是最适合ts的编辑器,而且这个编辑器本身也很好用,所以学一下 ...

  7. va_list 简介

    原文:http://blog.sina.com.cn/s/blog_590be5290100qhxr.html va_list是一个宏,由va_start和va_end界定. typedef char ...

  8. logging模块详解以及常见代码

    1.在django中获取客户端IP地址: if 'HTTP_X_FORWARDED_FOR' in request.META: ip = request.META['HTTP_X_FORWARDED_ ...

  9. luogu P2746 [USACO5.3]校园网Network of Schools

    题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写 ...

  10. NLP项目

    GitHub NLP项目:自然语言处理项目的相关干货整理 自然语言处理(NLP)是计算机科学,人工智能,语言学关注计算机和人类(自然)语言之间的相互作用的领域.本文作者为自然语言处理NLP初学者整理了 ...