匈牙利算法
有vN 和uN两个点集构成的二分图
通过深度遍历, 找u0-u1匹配增广轨 --------
为u0找增光轨找到res++ 连线
为u1找增广轨找到res++连线
为u2找增广轨 假如u2能匹配v5,v6的都被u1,u0分别连接那么试图改变u1,u0的连接对象 给u2腾出v5或者v6位置 腾出来就连接res++
诸如此类直到整个遍历结
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=510;
int uN,vN;//u,v数目
int g[MAXN][MAXN]; //图
int linker[MAXN];
bool used[MAXN];
bool dfs(int u) //从uN点集开始找增广路径
{
int v;
for(v=0;v<vN;v++) //对于每个u 遍历Vn点集,这个顶点编号从0开始
if(g[u][v]&&!used[v]) //如果这个uv顶点连通,且他还没有被used封锁 就是是增广轨
{
used[v]=true; //这个顶点进行used封锁 本次dfs更深度递归不再使用 hungry 中u变化使used会初始化
if(linker[v]==-1||dfs(linker[v])) //未被连线 直接连线 ||如果v点集的改点v'已经被连线 那么试图更改他连的曾经连接的u'的连线 让他成为未被连线 与当前u连线
{ //找增广路,反向
linker[v]=u; //v u连线
return true;
}
}
return false; //这里主要用于递归 判断非used封锁下 能够连线吗 就是能够腾位置吗
}
int hungry()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker)); //初始化linker 连线
for(u=0;u<uN;u++) //从uN点集遍历
{
memset(used,0,sizeof(used)); //初始化used
if(dfs(u)) res++;
}
return res; //返回最大点覆盖集
}
int main()
{
while(cin>>uN>>vN)
{
for(int i=0;i<uN;i++)
for(int j=0;j<uN;j++)
{
cin>>g[i][j];
}
cout<<hungry();
}
}
匈牙利算法详解参考:http://blog.youkuaiyun.com/dark_scope/article/details/8880547/ (写的很好,我是看着个看懂的:) )