HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流:
1 //题目大意:有编号为1~n的女生和1~n的男生配对
2 //
3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架
4 //
5 //然后输入f组,c,d表示编号为c的女生和编号为d的女生是朋友
6 //
7 //进行配对的要求满足其一即可。
8 //1.a女生没有和b男生吵过架
9 //2.a女生的朋友和b男生没有吵过架
10 //
11 //每进行一轮之后重新配对,配过得一对不可再配,问最多能进行几轮。
12 //
13 //题解:
14 //这一道题要二分答案,然后用最大流来跑
15 //可能很疑惑最大流怎么去跑这个题目,我们可以假设可以进行mid轮,然后我们从起点给女生连一条容量为mid的
16 //边,然后终点也和男孩之间连一条容量为mid的边。之后如果男孩和女孩之间可以组成情侣那就连一条容量为1的
17 //边。这样的话当mid==1的时候,你跑最大流相当于每一个女孩找到了一个互不相同的男孩(因为一个男孩和终点容
18 //量为1,对吧!!),当mid>1的时候,这个时候对于一个男孩可以被选择mid次(保证这个mid是可行解),因为每一
19 //个女生和一个男生的边容量只是1,所以一个女生不可能选择多次是同一个男生。那么对于所有男生都会有mid个
20 //女生选择他们,那么这样的话就刚好可以凑成mid轮
21
22 #include<stdio.h>
23 #include<string.h>
24 #include<iostream>
25 #include<algorithm>
26 #include<queue>
27 using namespace std;
28 const int maxn=1010;
29 const int INF=0x3f3f3f3f;
30 int head[maxn],cnt,st,en,dis[maxn],cur[maxn],w[105][105],q[105][105];
31 struct edge
32 {
33 int v,next,c,flow;
34 } e[100000];
35 void add_edge(int x,int y,int z)
36 {
37 e[cnt].v=y;
38 e[cnt].c=z;
39 e[cnt].flow=0;
40 e[cnt].next=head[x];
41 head[x]=cnt++;
42
43 e[cnt].v=x;
44 e[cnt].c=0;
45 e[cnt].flow=0;
46 e[cnt].next=head[y];
47 head[y]=cnt++;
48 }
49 bool bfs()
50 {
51 memset(dis,0,sizeof(dis));
52 dis[st]=1;
53 queue<int>r;
54 r.push(st);
55 while(!r.empty())
56 {
57 int x=r.front();
58 r.pop();
59 for(int i=head[x]; i!=-1; i=e[i].next)
60 {
61 int v=e[i].v;
62 if(!dis[v] && e[i].c>e[i].flow)
63 {
64 dis[v]=dis[x]+1;
65 r.push(v);
66 }
67 }
68 }
69 return dis[en];
70 }
71 int dinic(int s,int limit)
72 {
73 if(s==en || !limit) return limit;
74 int ans=0;
75 for(int &i=cur[s]; i!=-1; i=e[i].next)
76 {
77 int v=e[i].v,feed;
78 if(dis[v]!=dis[s]+1) continue;
79 feed=dinic(v,min(limit,e[i].c-e[i].flow));
80 if(feed)
81 {
82 e[i].flow+=feed;
83 e[i^1].flow-=feed;
84 limit-=feed;
85 ans+=feed;
86 if(limit==0) break;
87 }
88 }
89 if(!ans) dis[s]=-1;
90 return ans;
91 }
92 int main()
93 {
94 int t;
95 scanf("%d",&t);
96 while(t--)
97 {
98 memset(w,0,sizeof(w));
99 memset(q,0,sizeof(q));
100 st=0;
101 int n,m,f,x,y;
102 scanf("%d%d%d",&n,&m,&f);
103 en=2*n+1;
104 for(int i=1; i<=m; ++i)
105 {
106 scanf("%d%d",&x,&y);
107 q[x][y]=1;
108 }
109 for(int i=1; i<=f; ++i)
110 {
111 scanf("%d%d",&x,&y);
112 w[x][y]=w[y][x]=1;
113 }
114
115 int l=0,r=n,mid,flag=0,sum;
116 while(l<=r)
117 {
118 mid=(l+r)>>1;
119 memset(head,-1,sizeof(head));
120 cnt=0;
121 for(int i=1; i<=n; ++i)
122 {
123 add_edge(st,i,mid);
124 add_edge(i+n,en,mid);
125 }
126 for(int i=1; i<=n; ++i)
127 {
128 for(int j=1; j<=n; ++j)
129 {
130 if(i==j) continue;
131 if(w[i][j])
132 {
133 for(int k=1; k<=n; ++k)
134 {
135 if(q[j][k])
136 {
137 q[i][k]=1;
138 }
139 }
140 }
141 }
142 }
143 for(int i=1; i<=n; ++i)
144 {
145 for(int j=1; j<=n; ++j)
146 {
147 if(q[i][j])
148 add_edge(i,j+n,1);
149 }
150 }
151 int ans=0;
152 while(bfs())
153 {
154 for(int i=0; i<=en; i++)
155 cur[i]=head[i];
156 ans+=dinic(st,INF); //这里原来是1我改成了INF,是这里的错.变成1的话最大流算法跑了好多次,就会TLE
157 }
158 if(ans>=n*mid)
159 {
160 sum=mid;
161 l=mid+1;
162 }
163 else r=mid-1;
164 }
165
166 printf("%d\n",sum);
167
168 }
169 return 0;
170 }
二分匹配:
1 //还可以用二分图匹配+并查集来写(我是用的最大流,以下代码转自:https://blog.csdn.net/loy_184548/article/details/51461601)
2 //
3 //题目大意:有编号为1~n的女生和1~n的男生配对
4 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架
5 //
6 //然后输入f组,c,d表示编号为c的女生和编号为d的女生是朋友
7 //
8 //进行配对的要求满足其一即可。
9 //1.a女生没有和b男生吵过架
10 //2.a女生的朋友和b男生没有吵过架
11 //
12 //每进行一轮之后重新配对,配过得一对不可再配,问最多能进行几轮。
13 //
14 //题目思路:
15 //第一步:要求2可以处理一下变成要求1.这里就需要用到并查集啦(刚开始用dfs处理,然而超内存了)
16 //1.两个女生是朋友就用并查集合并
17 //2.遍历,如果两个女生a,b父节点一样,那么b所能配对的男生a也能配对
18
19 // 链接:https://blog.csdn.net/loy_184548/article/details/51461601
20 // HDU-3081.cpp
21 // HDU
22 //
23 // Created by pro on 16/5/20.
24 // Copyright (c) 2016年 loy. All rights reserved.
25 //
26
27 #include <iostream>
28 #include <cstdio>
29 #include <cmath>
30 #include <vector>
31 #include <cstring>
32 #include <algorithm>
33 #include <string>
34 #include <set>
35 #include <functional>
36 #include <numeric>
37 #include <sstream>
38 #include <stack>
39 #include <map>
40 #include <queue>
41 #include<iomanip>
42 using namespace std;
43 int g[105][105];
44 #define MAXN 105
45 int fa[MAXN] = {0};
46 int vis[105];
47 int link[105]; //编号为i的女生对应的男生编号
48 int n,m,f,ans = 0;
49 void initialise(int n) //初始化
50 {
51 for (int i = 1; i <= n; i++)
52 fa[i] = i;
53 }
54 int getfather(int v) //父节点
55 {
56 return (fa[v] == v) ? v : fa[v] = getfather(fa[v]);
57 }
58 void merge(int x,int y) //合并
59 {
60 x = getfather(x);
61 y = getfather(y);
62 if (x != y)
63 fa[x] = y;
64 }
65
66 bool dfs(int u) {
67 for (int v = 1; v <= n; v++) {
68 if (!vis[v] && g[u][v]) {
69 vis[v] = 1;
70 if (!link[v] || dfs(link[v])) {
71 link[v] = u;
72 return true;
73 }
74 }
75 }
76 return false;
77 }
78 void solve()
79 {
80 while(1)
81 {
82 // cout << ans << endl;
83 memset(link,0,sizeof(link));
84 int cnt = 0;
85 for (int i = 1; i <= n; i++)
86 {
87 memset(vis,0,sizeof(vis));
88 if (dfs(i)) cnt++; //如果找到了能配对的
89 }
90 if (cnt == n) //如果全部配对成功
91 {
92 ans++;
93 for (int i = 1; i <= n; i++)
94 {
95 g[link[i]][i] = 0; //编号为i以及对应的女生不能再连
96 }
97 }
98 else
99 {
100 break;
101 }
102 }
103 }
104 int main()
105 {
106 int t;
107 scanf("%d",&t);
108 while(t--)
109 {
110 int u,v;
111 scanf("%d%d%d",&n,&m,&f);
112 memset(g,0,sizeof(g));
113 initialise(n);
114 ans = 0;
115 for (int i = 0; i < m; i++)
116 {
117 scanf("%d%d",&u,&v);
118 g[u][v] = 1;
119 }
120 for (int i = 0; i < f; i++)
121 {
122 scanf("%d%d",&u,&v);
123 merge(u,v);
124 }
125 for (int i = 1; i <= n; i++)
126 {
127 int t = getfather(i);//得到编号为i这个女生的父节点
128
129 for (int j = 1; j <= n; j++)
130 {
131 if (i != j && getfather(j) == t) //如果两个女生是朋友
132 {
133 for (int k = 1; k <= n; k++) //那么j的朋友k,也是i的朋友
134 {
135 if (g[j][k]) g[i][k] = 1;
136 }
137 }
138 }
139 }
140 solve();
141 printf("%d\n",ans);
142 }
143 return 0;
144 }
HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流的更多相关文章
- HDU 3081 Marriage Match II (二分图,并查集)
HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...
- 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 pid=3081" target="_blank" style="">题目链接 题意:n个 ...
- HDU 3081 Marriage Match II 二分 + 网络流
Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...
- HDU 3081 Marriage Match II 最大流OR二分匹配
Marriage Match IIHDU - 3081 题目大意:每个女孩子可以和没有与她或者是她的朋友有过争吵的男孩子交男朋友,现在玩一个游戏,每一轮每个女孩子都要交一个新的男朋友,问最多可以玩多少 ...
- HDU 3081 Marriage Match II
二分图的最大匹配+并查集 每次匹配完之后,删除当前匹配到的边. #include<cstdio> #include<cstring> #include<cmath> ...
- HDU 3081 Marriage Match II (二分+网络流+并查集)
注意 这题需要注意的有几点. 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时. 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是. 其次这题是多 ...
- HDU - 3081 Marriage Match II 【二分匹配】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...
- HDU 3081 Marriage Match II (二分+并查集+最大流)
题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮 ...
随机推荐
- Selenium WebDriver 定位之Xpath定位
Selenium 定位之Xpath定位: 1.绝对路径定位:以/开头从根节点一直找到当前节点,不推荐使用决定路径定位方式 2.相对路径定位:使用"//"表示相对路径定位,格式:// ...
- rename 表名
rename table 旧表名1 to 新表名1,旧表名2 to 新表名2;
- 【Linux】CentOS8 初体验
一.部署CentOS8虚拟机 1.下载Centos8镜像 下载地址: https://www.centos.org/download/ 可以选择国内的下载源,比较快,这里推荐清华的和阿里的 2.下载完 ...
- 【Python】用字母生成图像
用字母生成图像会用到matplotlib.pyplot库 所以需要安装这个库 pip install matplotlib 等待安装完成即可 ps:由于网络原因,会出现多次的timeout,可以使用国 ...
- python无法连接mysql,有个小坑,需要注意一下!
尝试用python链接mysql数据库,按照教程里链接了小半夜,就是没有链接上,找了各种文章,最后发现是版本的问题,我想使用的模块是MySQLdb,刚刚去他们的官网看了一下,最近一次更新是2014年, ...
- 源代码增强的一点说明(souce code enhance )
souce code enhance 分为显式和隐式两种. 下面以显式创建为例子: 1.在ABAP编辑器中, 打开想要编辑的程序,切换到可编辑模式 2.在源代码中的指定位置右键,弹出菜单,选择 Enh ...
- zabbix-server安装部署配置
zabbix-server安装部署配置 zabbixLinux安装部署安装脚本 1 一步一步部署 1.1 安装zabbix仓库源 这里安装阿里的zabbix仓库地址 选用zabbix版本3.4 rpm ...
- linux通过ntpd同步服务器时间,
ntpd得rpm包下载地址:https://pkgs.org/download/ntp 比如我得服务器版本是centos7 x86的,那选择我点击的这一个: 下拉到最下面就有安装包下载了,我选择的是二 ...
- 基于Vue的npm组件库
前言(*❦ω❦) 思维导图可能有点高糊,有点太大了,项目和导图文件放到github或giteee上,这个思维导图也是我文章的架构,思维导图是用FeHelper插件生成的,这个是一款开源chrome插件 ...
- java-数据类型复习
java中共有8种基本的数据类型,分别为 字节型byte(8字节,32位),短整型short(16字节),整型int(32字节),长整型long(64字节), 字符型char(16字节),浮点型flo ...