二分图最大匹配-匈牙利算法
2016-10-20 17:04
246 查看
二分图的定义:如果一个图的所有顶点可以被分为X和Y两个集合,并且所有边的两个顶点恰好一个属于集合X,另一个属于集合Y,即每个集合内的顶点没有边相连,那么此图就是二分图。
增广路:增广路的本质就是一条路径的起点和终点都是未被配对的点。
如果找到一条增广路,那么配对数将会加1.
寻找一个点配对的基本思路:
1.从点u开始,从点u引出的边中任意选一条边(u-v)开始配对。如果此时v还没有被配对,则配对成功,找到一条增广路。如果点v已被配对,就尝试进行“连锁反应”,如果尝试成功,则找到一条增广路,并更新配对关系。
2.如果刚才所选的边配对失败,就重新选一条边尝试。直到点u配对成功,或者尝试过点u所有的边为止。
#include<iostream>
#include<cstdio>
using namespace std;
int node[50],next[50],root[50],cnt,m,n;
int match[50],book[50];
//match[x]用来存储x配对的对象,book[x]标记x是否已被访问
int sum;
//二分图都是无向图
void insert(int u, int v) {
cnt++;
node[cnt] = v;
next[cnt] = root[u];
root[u] = cnt;
}
void build() {
for (int i=1; i<=m; i++) {
int u,v;
cin >> u >> v;
insert(u,v);
insert(v,u);
}
}
//寻找一个点的匹配
bool dfs(int u)
{
for (int x=root[u]; x!=-1; x=next[x])
if (!book[node[x]]) {
book[node[x]] = 1;
if (match[node[x]] == -1 || dfs(match[node[x]])) { //一旦发现寻找增广路可行(dfs的值为1),就向前返回修改match数组的值
match[node[x]] = u;
match[u] = node[x];
return 1; //找到增广路,返回 1
}
}
return 0; //连锁反应失败,返回 0
}
int main()
{
cin >> n >> m;
for (int i=1; i<=m; i++) next[i] = -1;
for (int i=1; i<=n; i++) root[i] = -1;
build();
for (int i=1; i<=n; i++) match[i] = -1;
for (int i=1; i<=n; i++) {
for (int j=1; j<=n; j++) book[j] = 0; //清空上次搜索时的访问标记,只留下match的配对标记。因为如一个点已经选过,可以引发连锁反应。
if (dfs(i)) sum++; //此时sum存储的是前i个点的最大匹配
//因为是最大匹配,所以只要找到一条增广路,sum就加1,后面的搜索是寻找有无新的增广路。
}
cout << sum;
return 0;
}
增广路:增广路的本质就是一条路径的起点和终点都是未被配对的点。
如果找到一条增广路,那么配对数将会加1.
寻找一个点配对的基本思路:
1.从点u开始,从点u引出的边中任意选一条边(u-v)开始配对。如果此时v还没有被配对,则配对成功,找到一条增广路。如果点v已被配对,就尝试进行“连锁反应”,如果尝试成功,则找到一条增广路,并更新配对关系。
2.如果刚才所选的边配对失败,就重新选一条边尝试。直到点u配对成功,或者尝试过点u所有的边为止。
#include<iostream>
#include<cstdio>
using namespace std;
int node[50],next[50],root[50],cnt,m,n;
int match[50],book[50];
//match[x]用来存储x配对的对象,book[x]标记x是否已被访问
int sum;
//二分图都是无向图
void insert(int u, int v) {
cnt++;
node[cnt] = v;
next[cnt] = root[u];
root[u] = cnt;
}
void build() {
for (int i=1; i<=m; i++) {
int u,v;
cin >> u >> v;
insert(u,v);
insert(v,u);
}
}
//寻找一个点的匹配
bool dfs(int u)
{
for (int x=root[u]; x!=-1; x=next[x])
if (!book[node[x]]) {
book[node[x]] = 1;
if (match[node[x]] == -1 || dfs(match[node[x]])) { //一旦发现寻找增广路可行(dfs的值为1),就向前返回修改match数组的值
match[node[x]] = u;
match[u] = node[x];
return 1; //找到增广路,返回 1
}
}
return 0; //连锁反应失败,返回 0
}
int main()
{
cin >> n >> m;
for (int i=1; i<=m; i++) next[i] = -1;
for (int i=1; i<=n; i++) root[i] = -1;
build();
for (int i=1; i<=n; i++) match[i] = -1;
for (int i=1; i<=n; i++) {
for (int j=1; j<=n; j++) book[j] = 0; //清空上次搜索时的访问标记,只留下match的配对标记。因为如一个点已经选过,可以引发连锁反应。
if (dfs(i)) sum++; //此时sum存储的是前i个点的最大匹配
//因为是最大匹配,所以只要找到一条增广路,sum就加1,后面的搜索是寻找有无新的增广路。
}
cout << sum;
return 0;
}
相关文章推荐
- 二分图最大匹配(匈牙利算法)
- 二分图的最大匹配(匈牙利算法)
- poj3041二分图的最大匹配匈牙利算法
- [Matrix67]二分图最大匹配问题匈牙利算法
- POJ 1274The Perfect Stall (二分图最大匹配问题,匈牙利算法实现)
- 二分图最大匹配问题匈牙利算法
- (资料)二分图(偶图)最大匹配解法之一匈牙利算法
- Pku acm 3041 Asteroids 数据结构题目解题报告(十六)---- 匈牙利算法求二分图的最大匹配
- Pku acm 2771 Guardian of Decency 数据结构题目解题报告(十五)---- 匈牙利算法求二分图的最大匹配
- 二分图最大匹配 - 匈牙利算法
- 二分图最大匹配 匈牙利算法
- 匈牙利算法求二分图的最大匹配
- 匈牙利算法 (二分图的最大匹配)
- Pku acm 1466 Girls and Boys数据结构题目解题报告(十七)---- 匈牙利算法求二分图的最大匹配
- 二分图的最大匹配匈牙利算法和最小支配集
- 用匈牙利算法求二分图的最大匹配
- 二分图最大匹配(匈牙利算法)
- Pku acm 2239 Selecting Courses 数据结构题目解题报告(十二)---- 匈牙利算法求二分图的最大匹配
- 二分图最大匹配 匈牙利算法 (自己写的模板)
- Pku acm 2536 Gopher II 数据结构题目解题报告(十四)---- 匈牙利算法求二分图的最大匹配