二分+最大流:

  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. mysql: Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/share/mysql/charsets/Index.xml' file

    mysql: Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/sha ...

  2. 【Linux】ethtool 用法

    ethtool命令用于获取以太网卡的配置信息,或者修改这些配置.这个命令比较复杂,功能特别多. 语法 ethtool [ -a | -c | -g | -i | -d | -k | -r | -S | ...

  3. cursor pin s和cursor pin s wait on x

    1.cursor pin s是一个共享锁,一般情况下是因为发生在SQL短时间内大量执行 案例:在生产库中,突然出现大量的cursor pin s的等待,询问是否有动作后,同事说有编译存储过程(被误导了 ...

  4. Doris

    Doris 基本概念 Doris 是基于 MPP 架构的交互式 SQL 数据仓库,主要用于解决近实时的报表和多维分析. Doris 分成两部分 FE 和 BE ,FE 负责存储以及维护集群元数据.接收 ...

  5. java 利用异或^进行加密

    package com.zcj.eg001; import java.nio.charset.Charset; import org.junit.Test; public class Encrypti ...

  6. Zabbix监控虚拟机服务-告警与自动恢复

    今天稍微空闲,使用下zabbix的5.0版本,目前生产环境是4.x版本 今天就只实现一个目的:监控任意一个服务(示例中监控的是docker.service),如果服务挂了,自动给恢复,先看一个动图 搭 ...

  7. [USACO13DEC]牛奶调度Milk Scheduling

    原题链接https://www.lydsy.com/JudgeOnline/problem.php?id=4096 容易想到的一个测略就是,优先考虑结束时间小的牛.所以我们对所有牛按照结束时间排序.然 ...

  8. [从源码学设计]蚂蚁金服SOFARegistry之延迟操作

    [从源码学设计]蚂蚁金服SOFARegistry之延迟操作 0x00 摘要 SOFARegistry 是蚂蚁金服开源的一个生产级.高时效.高可用的服务注册中心. 本系列文章重点在于分析设计和架构,即利 ...

  9. 【CentOS7】Apache发布静态网页-超简单

    目前能够提供Web网络服务的程序有 IIS. Nginx和 Apache等.其中,IIS (Internet Information Services,互联网信息服务)是 Windows系统中默认的 ...

  10. error: Failed dependencies: rpm安装包失败报错依赖包

    error: Failed dependencies: mysql-community-release conflicts with (installed) mysql57-community-rel ...