二分+最大流:

  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 二分+最大流的更多相关文章

  1. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

  2. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  3. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

  4. HDU 3081 Marriage Match II 二分 + 网络流

    Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...

  5. HDU 3081 Marriage Match II 最大流OR二分匹配

    Marriage Match IIHDU - 3081 题目大意:每个女孩子可以和没有与她或者是她的朋友有过争吵的男孩子交男朋友,现在玩一个游戏,每一轮每个女孩子都要交一个新的男朋友,问最多可以玩多少 ...

  6. HDU 3081 Marriage Match II

    二分图的最大匹配+并查集 每次匹配完之后,删除当前匹配到的边. #include<cstdio> #include<cstring> #include<cmath> ...

  7. HDU 3081 Marriage Match II (二分+网络流+并查集)

    注意 这题需要注意的有几点. 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时. 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是. 其次这题是多 ...

  8. HDU - 3081 Marriage Match II 【二分匹配】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...

  9. HDU 3081 Marriage Match II (二分+并查集+最大流)

    题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮 ...

随机推荐

  1. ctfhub技能树—密码口令—默认口令

    打开靶机 查看页面内容 根据题目提示,去搜索北京亿中邮信息技术有限公司邮件网关的默认口令 尝试登录 成功拿到flag

  2. SAP中使用FTP服务

    SAP中简单的FTP技术实现基本上如下几个步骤: 1.SM59建立FTP的RFC destination. 可以通过执行SAP的标准程序RSFTP005,自动创建两个名为SAPFTP何SAPFTPA的 ...

  3. 02--Docker配置阿里云镜像加速器

    1.登录阿里云控制台,在产品与服务中收索 "容器镜像服务" 2.点击镜像加速器,CentOS 3.在路径 /etc/docker/daemon.json 下配置加速器地址 4.重新 ...

  4. uni-app 微信小程序 picker 三级联动

    之前做过一个picker的三级联动功能,这里分享代码给大家 具体代码: // An highlighted block <template> <view> <picker ...

  5. k8s之共享存储概述以及演示

    共享存储机制 k8s对有状态的容器应用或者需要对数据进行持久化的应用,在之前的篇章说过,可以将容器内的目录挂载到宿主机的容器目录或者emptyDir临时存储卷. 另外,k8s还开放了两个资源,分别是P ...

  6. Docker的Ubuntu镜像安装的容器无ifconfig命令和ping命令

    就这三步骤,下面的是实例不看也罢. apt-get update ###第一步一定要先执行这个更新下.不更新下面的安装命令会显示找不到网络包 //ifconfig apt install net-to ...

  7. jQuery mock.js模拟的使用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  8. Web自动化测试python环境中安装 --selenium安装、火狐和火狐驱动版本、谷歌和谷歌驱动版本、测试

    一.安装selenium Windows命令行(cmd)输入pip install selenium(无须指定版本默认最新)或 pip install selenium==3.141.0(可指定版本) ...

  9. A1Z26 Cipher - Letter Number A=1 B=2 C=3 - Online Decoder, Translator https://www.dcode.fr/letter-number-cipher

    A1Z26 Cipher - Letter Number A=1 B=2 C=3 - Online Decoder, Translator https://www.dcode.fr/letter-nu ...

  10. 正则r的作用

    >>> mm = "c:\\a\\b\\c" >>> mm 'c:\\a\\b\\c' >>> print(mm) c:\a\ ...