Marriage Match II 【HDU - 3081】【并查集+二分答案+最大流】
一开始是想不断的把边插进去,然后再去考虑我们每次都加进去边权为1的边,直到跑到第几次就没法继续跑下去的这样的思路,果不其然的T了。
然后,就是想办法咯,就想到了二分答案。
首先,我们一开始处理关系,(一开始看错了男女关系,结局懵逼了好久),注意输入是女选男。然后,就是去处理咯,我们先要去考虑,女生之间为朋友的话,又由于朋友关系是可以推的,所以我们不妨用并查集去维护这层关系,并且把总的关系推上到并查集的根上去。
然后,就是怎么样去想这个二分答案的过程了,我们可以假设玩了x轮,这么就代表了每个女孩纸被选择了x次,每个男孩纸也被选择了x次,(两者少了其中一者都不行)。那么,我们是不是可以从源点连到每个女孩纸的边权是x,然后从每个男孩纸连到汇点的边权是x。然后男孩、女孩之间的关系,就是我们之前并查集处理出来的了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = , maxE = 3e4 + , st = ;
int N, M, fr, head[maxN], cur[maxN], cnt, ed, root[maxN], mod_cnt, mod_head[maxN];
bool mp[maxN][maxN];
int fid(int x) { return x == root[x] ? x : (root[x] = fid(root[x])); }
struct Eddge
{
int nex, to, flow;
Eddge(int a=-, int b=, int c=):nex(a), to(b), flow(c) {}
}model[maxE], edge[maxE];
inline void addEddge(int u, int v, int w)
{
edge[cnt] = Eddge(head[u], v, w);
head[u] = cnt++;
}
inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, ); }
int deep[maxN];
queue<int> Q;
inline bool bfs()
{
for(int i=; i<=ed; i++) deep[i] = ;
while(!Q.empty()) Q.pop();
Q.push(st); deep[st] = ;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i=head[u], v, f; ~i; i=edge[i].nex)
{
v = edge[i].to; f = edge[i].flow;
if(f && !deep[v])
{
deep[v] = deep[u] + ;
Q.push(v);
}
}
}
return deep[ed];
}
inline int dfs(int u, int dist)
{
if(u == ed) return dist;
for(int &i=cur[u], v, f; ~i; i=edge[i].nex)
{
v = edge[i].to; f = edge[i].flow;
if(f && deep[v] == deep[u] + )
{
int di = dfs(v, min(dist, f));
if(di)
{
edge[i].flow -= di;
edge[i^].flow += di;
return di;
}
}
}
return ;
}
inline int Dinic()
{
int ans = , tmp;
while(bfs())
{
for(int i=; i<=ed; i++) cur[i] = head[i];
while((tmp = dfs(st, INF))) ans += tmp;
}
return ans;
}
struct Query
{
int u, v;
Query(int a=, int b=):u(a), v(b) {}
}qes[];
inline void init()
{
cnt = ; ed = (N<<) + ;
memset(head, -, sizeof(head));
for(int i=; i<=N; i++) root[i] = i;
for(int i=; i<=N; i++) for(int j=; j<=N; j++) mp[i][j] = false;
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &N, &M, &fr);
init();
for(int i=, u, v; i<=M; i++)
{
scanf("%d%d", &u, &v);
mp[u][v] = true;
}
for(int i=, u, v, fu, fv; i<=fr; i++)
{
scanf("%d%d", &u, &v);
fu = fid(u); fv = fid(v);
if(fu == fv) continue;
root[fu] = fv;
for(int j=; j<=N; j++)
{
if(mp[fu][j] && !mp[fv][j]) mp[fv][j] = true;
}
}
for(int i=, u; i<=N; i++)
{
u = fid(i);
for(int j=; j<=N; j++)
{
if(mp[u][j]) _add(i, j + N, );
}
}
mod_cnt = cnt;
for(int i=; i<cnt; i++) model[i] = edge[i];
for(int i=; i<=ed; i++) mod_head[i] = head[i];
int ans = , l = , r = N, mid = ;
while(l <= r)
{
mid = (l + r) >> ;
cnt = mod_cnt;
for(int i=; i<cnt; i++) edge[i] = model[i];
for(int i=; i<=ed; i++) head[i] = mod_head[i];
for(int i=; i<=N; i++)
{
_add(st, i, mid);
_add(i + N, ed, mid);
}
if(Dinic() >= N * mid)
{
ans = mid;
l = mid + ;
}
else r = mid - ;
}
printf("%d\n", ans);
}
return ;
}
Marriage Match II 【HDU - 3081】【并查集+二分答案+最大流】的更多相关文章
- N - Marriage Match II - HDU 3081(最大流)
题目大意:有一些男孩和女孩玩一个游戏,每个女孩都可以挑一个男孩来进行这个游戏(所有人都要参加),女孩只会挑选她喜欢的男孩,并且她们认为她们朋友喜欢的男孩她们也是喜欢的(朋友的男朋友也是我的男朋友??? ...
- Marriage Match II HDU - 3081(二分权值建边)
题意: 有编号为1~n的女生和1~n的男生配对 首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 然后输入f组,c,d表示编号为c的女生和编号为d的女生是朋友 进行配对的要求满足其一即 ...
- HDU 3277 Marriage Match III(并查集+二分答案+最大流SAP)拆点,经典
Marriage Match III Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流
题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others) ...
- HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...
- HDU 3081 Marriage Match II(二分法+最大流量)
HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- HDU 3081 Marriage Match II (二分图,并查集)
HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...
- HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))
Marriage Match II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
随机推荐
- Python笔记(读取txt文件中的数据)
在机器学习中,常常需要读取txt文本中的数据,这里主要整理了两种读取数据的方式 数据内容 共有四列数据,前三列为特征值,最后一列为数据标签 40920 8.326976 0.953952 3 1448 ...
- c++知识点总结3
http://akaedu.github.io/book/ week1 引用:相当于变量的别名.下面r和n就相当于同一回事 ; int &r=n; 引用做函数参数: void swap(int ...
- java 回调的原理与实现
回调函数,顾名思义,用于回调的函数.回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数.回调函数是一个工作流的一部分,由工作流来决定函数的调用(回调)时机. 回调原本应该是一个非常简 ...
- 网络拓扑_配置VLAN虚拟局域网
目的: 1.创建VLAN10,VALN20,VLAN30; 2.将端口加入VLAN 3.查看VLAN信息 拓扑图: 步骤: 1.在三层交换机中创建VLAN10,VLAN20,VLAN30 <Hu ...
- maven_上传到私服,以及从私服下载
公司由于没有maven,自己又想用,于是乎,就自己搭了一个nexus 1.苦逼不多说,将本地jar文件上传到maven 需要在本机(客户端windows)中的maven中的setting.xml添加这 ...
- Java面向对象(二) 接口、多态和泛型
一.接口 二.多态 多态是同一个行为具有多个不同表现形式或形态的能力. 2.1 类型转换 转换方式 隐式 向上转型 对于基本数据类型,存储容量低的可自动向存储容量高的类型转换 对于引用变量,子类可被转 ...
- linux下caffe的命令运行脚本
参考:https://www.cnblogs.com/denny402/p/5076285.html 首先编译: make -j8 make pycaffe 注:下面的--solver=.... 等价 ...
- Java缓冲字符读取
public class BufferedReaderDemo { public static void main(String[] args) throws IOException { // 创建流 ...
- Java 输入输出图片文件的简单方式
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...
- 英语单词independent
来源——https://www.docker.com/products/docker-hub 回到顶部 Share and Collaborate with Docker Hub Docker Hub ...