nyoj-239 月老的难题 (二分图匹配—匈牙利算法 网络流—Dinic算法)
月老的难题
- 描述
-
月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘。
现在,由于一些原因,部分男孩与女孩可能结成幸福的一家,部分可能不会结成幸福的家庭。
现在已知哪些男孩与哪些女孩如果结婚的话,可以结成幸福的家庭,月老准备促成尽可能多的幸福家庭,请你帮他找出最多可能促成的幸福家庭数量吧。
假设男孩们分别编号为1~n,女孩们也分别编号为1~n。
- 输入
-
第一行是一个整数T,表示测试数据的组数(1<=T<=400)
每组测试数据的第一行有两个整数n,K,其中男孩的人数与女孩的人数都是n。(n<=500,K<=10 000)
随后的K行,每行有两个整数i,j表示第i个男孩与第j个女孩有可能结成幸福的家庭。(1<=i,j<=n) - 输出
- 对每组测试数据,输出最多可能促成的幸福家庭数量
- 样例输入
-
1 3 4 1 1 1 3 2 2 3 2
- 样例输出
-
2
思路:
此题是经典的二分图匹配模板题,学习网络流后发现也可解(只需加一个超级源点和超级汇点,就变成了网路流的模板题)。刚好初学这两种算法,便将此题作为模板题整理下来;二分图匈牙利算法与网络流的Dinic算法耗时相当,但网络流(使用邻接表建图)的空间消耗较大;
二分图匹配—匈牙利算法, 资料:http://kukumayas.iteye.com/blog/1075610
http://blog.csdn.net/niushuai666/article/details/7023101
匈牙利算法代码:
#include <stdio.h> #include <string.h> #include <vector> #define N 520using namespace std;int P_Num; // 人数 vector<int>Boy[N]; // 临界表,保存匹配信息 bool use[N]; // 标记数组 int form[N]; // 父节点(i号女生对应的男生编号) bool Match(int cur){ // 匹配函数 for(int i = 0; i < Boy[cur].size(); i ++){ // 遍历所有能与cur男生匹配的女生 if(!use[ Boy[cur].at(i) ]){ // 判断该女生结点是否被判断过,没有进入 use[ Boy[cur].at(i) ] = 1; // 标记该女生已经判断 if(form[ Boy[cur].at(i) ] == -1 || Match(form[ Boy[cur].at(i) ])){ // 如果该女生未被匹配,或者之前匹配该女生的男生可以匹配其它女生 form[ Boy[cur].at(i) ] = cur; // 则将该女生匹配给cur男生return 1; // 成功匹配返回1 }}}return 0; }int Hungary(){ // 匈牙利算法 int count = 0; // 计数器 memset(form, -1, sizeof(form)); // form保存女生对应的男生的编号,初始化为-1 for(int i = 1; i <= P_Num; i ++){ // 遍历每个男生结点,与女生深搜匹配 memset(use, 0, sizeof(use)); // 匹配前先将标记数组清零,起作用是防止重复搜索某结点 count += Match(i);}return count; }int main() {int loop, G_Num;scanf("%d", &loop);while(loop --){int start, end;scanf("%d%d", &P_Num, &G_Num);for(int i = 1; i <= P_Num; i ++){ // 多组数据初始化,清空数组 Boy[i].clear();}for(int i = 0; i < G_Num; i ++){scanf("%d%d", &start, &end);Boy[start].push_back(end);}int ans = Hungary();printf("%d\n", ans);}return 0; }
-
网络流代码:
-
#include <stdio.h> #include <string.h> #include <queue> #define INF 0x7fffffff #define N 1020using namespace std;struct Node{int to;int weight;int next; };Node edge[N * 100]; int head[N]; int level[N]; int edge_n;int min(int a, int b) {return a < b ? a : b; }void AddEdge(int start, int end, int weight) {edge[edge_n].to = end;edge[edge_n].weight = weight;edge[edge_n].next = head[start];head[start] = edge_n ++;edge[edge_n].to = start;edge[edge_n].weight = 0;edge[edge_n].next = head[end];head[end] = edge_n ++; }bool bfs(int start, int end) {memset(level, 0, sizeof(level));queue<int>q;q.push(start);level[start] = 1;int cur;while(!q.empty()){cur = q.front();q.pop();for(int i = head[cur]; i != -1; i = edge[i].next){int v = edge[i].to;int w = edge[i].weight;if(w > 0 && !level[v]){level[v] = level[cur] + 1;if(v == end){return 1;}q.push(v);}}}return 0; }int dfs(int cur, int end, int cp) {if(cur == end){return cp;}int t, tmp = cp;for(int i = head[cur]; i != -1 && tmp; i = edge[i].next){int v = edge[i].to;int w = edge[i].weight;if(level[v] == level[cur] + 1 && w > 0){t = dfs(v, end, min(tmp, w));edge[i].weight -= t;edge[i ^ 1].weight += t;tmp -= t;}}return cp - tmp; }int Dinic(int start, int end) {int ans = 0, min_w;while( bfs(start, end) ){while( min_w = dfs(start, end, INF) ){ans += min_w;}}return ans; }int main() {int loop, ans;int p_num, ct; // 男女人数,关系数目int boy_i, girl_i;scanf("%d", &loop);while(loop --){edge_n = 0;memset(head, -1, sizeof(head));scanf("%d%d", &p_num, &ct);while(ct --){ // 建图scanf("%d%d", &boy_i, &girl_i);AddEdge(boy_i, girl_i + p_num, 1);}int src = 0, des = p_num * 2 + 1; // 超级源点,超级汇点for(int i = 1; i <= p_num; i ++){AddEdge(src, i, 1);AddEdge(i + p_num, des, 1);}ans = Dinic(src, des);printf("%d\n", ans);}return 0; }
nyoj-239 月老的难题 (二分图匹配—匈牙利算法 网络流—Dinic算法)相关推荐
- NYOJ - 239 - 月老的难题 ( 二分图最大匹配 匈牙利算法 )
描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一家,部分可能不会结成幸福的家庭. 现在已知哪些男孩与哪些女孩如果结婚的话,可以结成幸 ...
- nyoj 239 月老的难题 【二分匹配之匈牙利】
月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一 ...
- NYOJ——239月老的难题(二分图最大匹配)
月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一家, ...
- nyoj 239 月老的难题
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=239 简单的二分匹配,不过这道题很怪,矩阵就是tle,临界表200多,很无语. 以前做个, ...
- NYOJ 题目239 月老的难题 (二分图最大匹配-匈牙利算法模板)
月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一 ...
- nyoj239 月老的难题 二分图 匈牙利算法
月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一 ...
- 二分图匹配匈牙利算法DFS实现
1 /*==================================================*\ 2 | 二分图匹配(匈牙利算法DFS 实现) 3 | INIT: g[][]邻接矩阵; ...
- 二分图匹配--匈牙利算法
文章目录 二分图: 匹配 匈牙利算法 代码: 二分图: 二分图是一个无向图,点集分成子集X和Y,图中每一条边都是一边在X一边在Y 当且仅当无向图G的每一个回路次数都是偶数时(包括0),G就是一个二分图 ...
- BZOJ.3140.[HNOI2013]消毒(二分图匹配 匈牙利)
题目链接 不难想到每次一定是切一片. 如果是平面,很容易想到直接做二分图匹配.对于3维的? 可以发现min(a,b,c)的最大值只有\(\sqrt[3]{n}≈17\),我们暴力枚举这一最小值代表的是 ...
最新文章
- 从Pix2Code到CycleGAN:2017年深度学习重大研究进展全解读
- 利用python+seleniumUI自动化登录获取cookie后再去测试接口,今天终于搞定了
- Android四大组件之——Activity的生命周期(图文详解)
- Android之属性动画初步
- 无代码时代来临,程序员如何保住饭碗?赶紧看一看!
- 五菱神车,昙花一现还是创造蓝海?
- 内河港口首次实现区块链无纸化进口放货
- 安装logstash5.4.1,并使用grok表达式收集nginx日志
- DOS命令taskkill
- docker registry push 覆盖_Maven一键部署Springboot到Docker仓库,为自动化做准备
- Java PC端微信、支付宝扫码支付(一)
- 操作系统——实验一(Linux基本操作)
- typora 主题下载及安装
- 定义复数java_java怎么定义复数?
- 电脑键盘部分按键失灵_笔记本键盘部分失灵怎么办,笔记本个别键失灵的处理方法...
- 移动端轮播图——网易云音乐手机端样式
- 办公室计算机打印机共享,如何将办公室的所有电脑共享一个打印机???
- c#加粗代码_C# 字体加粗按钮
- [USACO10HOL]赶小猪
- Unity动态构建Mesh来绘制任意多边形(雷达图效果)
热门文章
- 【UE4】导入FBX格式的模型至UE4
- DanmuVis: Visualizing Danmu Content Dynamics and AssociatedViewer Behaviors in Online Videos
- 矩阵转置算法 oracle,请编写程序fun,函数的功能是:实现B=A+Aˊ,即把矩阵A加上A的转置,存放在矩阵B中。计算结果在main函...
- DOM系列之排他思想
- sizeof(long)
- springcloud24:分布式事务 Seata处理分布式事务总结篇
- 01-计算机系统概述
- NEO改进协议提案9(NEP-9)
- 实现表格内容第一行居中,其他行与第一行左对齐
- 帝国时代3如何快速实现训练单位突破人口上限