[学习笔记]匈牙利算法

壹、模板测试链接

传送门

贰、说明

完美匹配一定是最大匹配,而最大匹配不一定是完美匹配.

交错路径:给定图G的一个匹配M,如果一条路径的边交替出现在M中和不出现在M中,我们称之为一条M-交错路径.

而如果一条M-交错路径,它的两个端点都不与M中的边关联,我们称这条路径叫做M-增广路径.

当图中再没有增广路径了,就意味着我们找到了该图的最大匹配了

二部图:给定两组顶点,但是组内的任意两个顶点间没有边相连,只有两个集合之间存在边,即组1内的点可以和组2内的点相连,这样构建出来的图就叫做二部图.

最大匹配是互相的,如果我们给X找到了最多的Y中的对应点,同样,Y中也不可能有更多的点得到匹配了

  1. 匈牙利算法寻找最大匹配,就是通过不断寻找原有匹配M的增广路径,因为找到一条M匹配的增广路径,就意味着一个更大的匹配M' , 其恰好比M 多一条边.

  2. 对于图来说,最大匹配不是唯一的,但是最大匹配的大小是唯一的.

这就是匈牙利的实现过程了.

叁、代码

using namespace Elaina;

const int maxn=500;
const int maxm=5e4;

struct edge{int to,nxt;}e[maxm+5];
int tail[maxn+5],ecnt;

int x,y,m;

inline void add_edge(const int u,const int v){
    e[++ecnt]=edge{v,tail[u]};tail[u]=ecnt;
}

inline void input(){
    x=readin(1),y=readin(1),m=readin(1);
    int u,v;
    rep(i,1,m){
        u=readin(1),v=readin(1);
        add_edge(u,v);
    }
}

int vis[maxn+5],match[maxn+5];
int dfs(const int u){
    for(int i=tail[u],v;i;i=e[i].nxt)if(!vis[v=e[i].to]){
        vis[v]=1;
        if(!match[v] || dfs(match[v])){
            match[v]=u;
            return 1;
        }
    }
    return 0;
}

signed main(){
    input();
    int ans=0;
    rep(i,1,x){
        memset(vis+1,0,y<<2);
        if(dfs(i))++ans;
    }
    writc(ans,'\n');
    return 0;
}
posted @ 2021-02-04 11:00  Arextre  阅读(76)  评论(0编辑  收藏  举报