HDU 5313 Bipartite Graph (二分图着色,dp)
题意:
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)的更多相关文章
- HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】
Bipartite Graph Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- HDU 5313 Bipartite Graph(二分图染色+01背包水过)
Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants ...
- hdu 5313 Bipartite Graph(dfs染色 或者 并查集)
Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants ...
- HDU 5313 Bipartite Graph
题意:给一个二分图,问想让二分图变成完全二分图最多能加多少条边. 解法:图染色+dp+bitset优化.设最终的完全二分图两部分点集为A和B,A中点个数为x,B中点个数为y,边数则为x × y,答案即 ...
- bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5006 https://www.luogu.org/problemnew/show/P4547 ...
- 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...
- 二分图点染色 BestCoder 1st Anniversary($) 1004 Bipartite Graph
题目传送门 /* 二分图点染色:这题就是将点分成两个集合就可以了,点染色用dfs做, 剩下的点放到点少的集合里去 官方解答:首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|*|Y|.我们的 ...
- HDU 5285 wyh2000 and pupil (二分图着色)
题意: 共有n个小学生,编号为1−n.将所有小学生分成2组,每组都至少有1个人.但是有些小学生之间并不认识,而且如果a不认识b,那么b也不认识a.Wyh2000希望每组中的小学生都互相认识.而且第一组 ...
- HDU 6321 Dynamic Graph Matching
HDU 6321 Dynamic Graph Matching (状压DP) Problem C. Dynamic Graph Matching Time Limit: 8000/4000 MS (J ...
随机推荐
- BestCoder Round #2
TIANKENG’s restaurant http://acm.hdu.edu.cn/showproblem.php?pid=4883 竟然暴力1.44*10^7 还要*T=100 竟然过了 # ...
- 《head first java 》读书笔记(二)
Updated 2014/03/27 P402-P454 Updated 2014/04/03 P454- 世界三大首席管理器: border, flow, box borderLayout: 五个区 ...
- hdu 3790 最短路径问题(最短路,Dijsktra)
题目 Dijsktra基础题,只是多了一个花费,稍稍变动处理就好 #define _CRT_SECURE_NO_WARNINGS #include<string.h> #include&l ...
- Ubuntu环境下手动配置ant
配置ant 1. 下载ant(http://ant.apache.org/bindownload.cgi) 例如我下载的是:apache-ant-1.9.4-bin.tar.gz 解压ant,将文件夹 ...
- lintcode:插入区间
题目: 插入区间 给出一个无重叠的按照区间起始端点排序的区间列表. 在列表中插入一个新的区间,你要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间). 样例 插入区间[2, 5] 到 [ ...
- XML DOS 攻击
内容来自此文:http://msdn.microsoft.com/en-us/magazine/ee335713.aspx DoS(Denial of service:拒绝服务)攻击由来已久(1992 ...
- 日志logger
1.使用指定类初始化日志对象 在日志输出的时候,可以打印出日志信息所在类如:Logger logger = LoggerFactory.getLogger(com.Book.class); ...
- 不用Invoke就等用 Control.CheckForIllegalCrossThreadCalls = false;
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)
原文地址: VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)-软件开发-鸡啄米 http://www.jizhuomi.com/software/139.html 上一讲中鸡 ...
- 250. Count Univalue Subtrees
题目: Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes ...