二分+最大流:

  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. kubernets之pv以及pvc

    一 持久卷以及持久卷声明的由来 由于不管是哪种卷,开发者都需要提前预知kubernets集群里面的存储类型,这样就在一定程度上违背了kubernets集群的设计理念,kubernets的设计理念是在由 ...

  2. 浏览器performance工具介绍及内存问题表现与监控内存的几种方式

    一.GC的目的 为了实现内存空间的良性循环,performance提供多种监控方式监控内存 分析内存相关信息 当代码出现问题的时候及时定位到出现问题的代码块, 提高执行效率. preforcemanc ...

  3. CVE-2020-0796复现

    今天整理资料时发现了之前存的一个cve漏洞复现过程,当时打算跟着复现来着,后来也没去复现,今天刚好有时间,所以来复现一下这个漏洞 漏洞讲解 https://www.freebuf.com/vuls/2 ...

  4. Empire

    Empire 内网渗透神器 一 基本渗透 安装 git clone https://github.com/BC-SECURITY/Empire/ ./setup/install.sh 启动 ./emp ...

  5. 分布式系统:分布式任务调度xxl-job较深入使用

    目录 系统关键概念介绍 执行器 任务 任务配置项描述 阻塞策略 路由策略 日志问题 客户端日志 服务端日志 框架目前发现的缺点以及存在的问题 xxl-job是一个分布式定时任务调度框架,功能强大,底层 ...

  6. git 基本命令和操作

    设置全局用户名+密码 $ git config --global user.name 'runoob' $ git config --global user.email test@runoob.com ...

  7. 计算机之路 -MySQL 初学

    照着电脑学了一天终于把MySQL装上了. 明天打算重新装一次 然后再自己记录一下步骤

  8. Python格式化处理json数据的方式

    1.问题 在遇到json数据的过程中,我们经常需要获取json数据中某个值的操作,如果是用get方法去取比较繁琐,接下来介绍两种方式来取值. 2.jsonpath来格式化处理json数据 2.1介绍 ...

  9. 下面给出一个child-parent的表格,要求挖掘其中的父子辈关系,给出祖孙辈关系的表格。

    package org.apache.hadoop.examples; import java.util.HashMap; import java.io.IOException; import jav ...

  10. 新编日语1234册/重排本/全册 pdf

    网上找的资源链接大部分都失效了,无奈之下只好淘宝购买.顺便分享一下吧. 链接: https://pan.baidu.com/s/1v5-osHKrIPzlgpd8yNIP5Q 提取码: kexn