二分图的最大匹配——匈牙利算法
来源:互联网 发布:js qq客服代码 编辑:程序博客网 时间:2024/05/22 15:18
背景知识:
什么是二分图?
二分图就是一种特殊的图。这个图可以将整个集合分成了两个子集,满足所有弧都是从其中一子集的顶点射向另一个子集的顶点。同一个子集中的点没有弧相连。
二分图的最大匹配:
二分图的最大匹配就是使两个集合的点尽可能多的一一对应。
本次介绍的是匈牙利算法。
匈牙利算法的原理就是寻找增广路径以扩大匹配数量。与最大流增广算法原理基本一致。
增广路径:
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。(百度百科)
源代码较长的原因是1.读入优化2.边表存储。
源代码的输入格式为POJ 1469所描述。
源代码:
/*About: 二分图最大匹配_匈牙利算法 From: POJ 1469 Auther: kongse_qiDate:2017/04/22*///#include <bits/stdc++.h>/* POJ的编译器不支持该头文件... */#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <string.h> #define maxn 10005 using namespace std;struct Edge{ int from; int to; int weight; Edge(){} //初始化 Edge(int f, int t, int w): from(f), to(t), weight(w){}//读入};//边表int times; /* 输入次数(多组数据) */int n, m, ans; /* 子集A的顶点数与子集B的顶点数 */vector<Edge> edge;vector<int> arc[maxn]; /* 存储每个起点所有的边在edge里的编号 */typedef vector<int>::iterator iterator_t; /* vector的迭代器 */bool check[maxn]; /* 用于检查是否已经匹配 */int match[maxn]; /* 对应的匹配节点 */char *X, *Buffer, c; /* fread读入优化 */int input; /* 同上 */void Get_All() /* 读入优化,一次读入整个文件 */{ long long file_lenth; fseek(stdin, 0, SEEK_END); file_lenth = ftell(stdin); rewind(stdin); Buffer = (char*)malloc(1*file_lenth); fread(Buffer,1, file_lenth, stdin); X = Buffer; return ;}void Get_Int() /* 将字符串转换为数字 */{ c = *X; input = 0; while(c < '0' || c > '9') c = *++X; while(c >= '0' && c <= '9') { input = input*10+c-'0'; c = *++X; } return ;}void Init() /* 由于是多组数据,需要将上一次的数据清空 */{ edge.resize(0); for(unsigned i = 0; i != n; ++i) { arc[i].resize(0); } ans = 0; return ;}void Read() /* 读入数据 */{ int cur, nums; Get_Int(), n = input; Get_Int(), m = input; for(unsigned i = 0; i != n; ++i) { edge.reserve(edge.size()); Get_Int(), nums = input; arc[i].resize(nums); for(unsigned j = 0; j != nums; ++j) { Get_Int(), cur = input; edge.push_back(Edge(i, cur+n, 0)); /*加n的原因是他的两集合的节点序号都是从1开始,需要分开 */ /* 如果用网络流做那么还需要将反向弧放入集合 */ arc[i][j] = edge.size()-1; /*编号 */ } } return ;}bool Dfs(int cur){ int cur_to; for(iterator_t i = arc[cur].begin(); i != arc[cur].end(); ++i) /* 遍历所有与cur节点相连的弧 */ { cur_to = edge[*i].to; /* 该弧终点 */ if(check[cur_to] == false) /* 如果当前未遍历到 */ { check[cur_to] = true; /* 那么此次遍历 */ if(match[cur_to] == -1 || Dfs(match[cur_to])) //如果当前节点为匹配或者它匹配的节点(递归)未匹配 { match[cur] = cur_to; /* 匹配两节点 */ match[cur_to] = cur; return true; /* 匹配成功,最大匹配数+1 */ } } } return false; /* 匹配未成功 */}void Match(){ memset(match, -1, sizeof match); for(unsigned i = 0; i != n; ++i) /* 所有节点均尝试匹配 */ { if(match[i] == -1) /* 如果当前节点未被匹配 */ { memset(check, 0, sizeof check); /* 将上一次匹配数据置空 */ if(Dfs(i)) /* 如果匹配成功 */ { ++ans; } } } return ;}int main(){ //freopen("test.in", "r", stdin); Get_All(); Get_Int(), times = input; while(times --> 0) /* times -= 1直到times == 0 */ { Init(); Read(); Match(); printf("%d\n", ans); } return 0;}
关于上文读入优化
关于上文的结构体初始化
自此结束。
箜瑟_qi 2017.04.22 15:47
0 1
- 二分图最大匹配—匈牙利算法
- 【二分图匹配】最大二分匹配——匈牙利算法
- 二分图的最大匹配——匈牙利算法
- 二分图的最大匹配——匈牙利算法
- 二分图的最大匹配—匈牙利算法
- 二分图的最大匹配2—匈牙利算法
- 二分图的最大匹配—匈牙利算法
- 二分图的最大匹配—匈牙利算法
- 匈牙利算法 (二分图的最大匹配)
- 二分图最大匹配的匈牙利算法
- 二分图最大匹配的匈牙利算法
- 二分图的最大匹配 (匈牙利算法)
- 二分图的最大匹配 匈牙利算法
- 二分图的最大匹配(匈牙利算法)
- 二分图的最大匹配:匈牙利算法
- 匈牙利算法-二分图的最大匹配
- 匈牙利算法,二分图的最大匹配
- 二分图最大匹配——匈牙利算法
- (c语言)在一个有数字的字符串中输出最长的数字
- PRML读书笔记——线性回归模型
- c++运算符重载的方法提要
- 选项卡控制器(tabBarController)基础
- 写给初学者22_android_百分比布局
- 二分图的最大匹配——匈牙利算法
- 【面试题】剑指Offer-50-求两个节点的最近公共祖先
- 二叉树的基本操作(严蔚敏)
- 深入理解LayoutInflater.inflate()
- JVM内存模型
- redis高级实用特性
- Python针对特定服务定制的代理工具V2.0------(zipdeal.py)
- Android--推送机制实现原理(四)-自己实现推送功能--心跳包
- ARM指令集发展概述