标签:复杂 fine return write png com 没有 i++ class
有一个无向图,如果所有的点可以被所有的边分成两个点集。则说这个图为二分图
下图就是一个标准二分图:
现有一个二分图E,还有它的子集M。如果M中任意一条边都没有公共的端点。则M是一个“匹配”
如果匹配M中,所有点都得到了一一匹配,则说M是一个“完全匹配”
那么我这篇文章就只写匈牙利,因为好写且好短。最大流这个坑以后我会填的(逃
噢还有上面那么的复杂度分析n是点数,m是边数
匈牙利算法的流程图解网上大把多好文章。那么我就推荐两个我当时看的吧
//阅读程序之前,请确保你阅读了我上面推荐的两个文章。
//因为本文视角是以“男女配对”看的(逃
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1005
using namespace std;
int n, m, q, ans;
int rel[maxn][maxn];
int mat[maxn];
bool vis[maxn];
bool dfs(int x)
{
for(int j = 1; j <= m; j++)
if(!vis[j] && rel[x][j])
//如果以前j这个女生跟x这个男生没有联系过并且x这个男生喜欢j这个女生
{
vis[j] = 1;
if(!mat[j] || dfs(mat[j]))
//如果这个女生没有人跟她配对
//或者她曾经配对成功的人可以跟另一个人私奔(那么这个女生不就没人配对了嘛)
{
mat[j] = x;
return 1;
}
}
return 0;
}
int main()
{
cin >> n >> m >> q;
for(int i = 1; i <= q; i++)
{
int u, v; cin >> u >> v;
if(v > m || u > n) continue;
rel[u][v] = 1;
/*
* 这里是建单向边。想想我们的配对过程,都是只关注一个点集
* 相对与另一个点集的情况
*/
}
for(int i = 1; i <= n; i++)
{
//vis数组是标记每个女生是否以前尝试跟i这个男生配对过。
//如果尝试配对过了,就不用再一次找她了,避免递归进入死循环
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
cout << ans;
return 0;
}
标签:复杂 fine return write png com 没有 i++ class
原文地址:https://www.cnblogs.com/BigYellowDog/p/10347294.html