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 ...
随机推荐
- H5下拉刷新特效demo,动画流畅
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- uva 10158
并查集 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #in ...
- Test a ; vs Test a( ) ;
一. Test a(); Test a; //前提声明了Test类 前者声明一个返回值为Test,名为a的函数,后者声明了Test类的一个对象(把Test当成int) struct Test{ ...
- Asp.Net缓存(2)
缓存页的多个版本 ASP.NET 允许在输出缓存中缓存同一页的多个版本.输出缓存可能会因下列因素而异: 初始请求 (HTTP GET) 中的查询字符串. 回发时传递的控制值(HTTP POST 值). ...
- JavaWeb项目开发案例精粹-第3章在线考试系统-006实体层
1. package com.sanqing.po; /* * 学生表,保存学生编号,系统密码 */ public class Student { private String studentID; ...
- nslookup工具的使用方法
配置好DNS服务器,添加了相应的记录之后,只要IP地址保持不变,一般情况下我们就不再需要去维护DNS的数据文件了.不过在确认域名解释正常之前我们最好是测试一下所有的配置是否正常.许多人会简单地使用pi ...
- 68. Text Justification
题目: Given an array of words and a length L, format the text such that each line has exactly L charac ...
- Linux下安装、配置、启动Apache
http://www.cnblogs.com/zhuque/archive/2012/11/03/2763352.html#
- Java API ——Collection集合类 & Iterator接口
对象数组举例: 学生类: package itcast01; /** * Created by gao on 15-12-9. */ public class Student { private St ...
- 基于SimHash的微博去重
一.需求:对微博数据进行去重,数据量比较小,几十万条左右. 二.解决方案 1.采用SimHash的指纹信息去重方法. 三.实现方案 1.对每一条微博使用tf-idf与特征词 2.使用每条微博的特征词, ...