zoukankan      html  css  js  c++  java
  • 【图论】浅析匈牙利算法

    本文不对匈牙利算法的证明作解释。

    预备知识

    • 二分图: 设 (G=(V,E)) 是一个无向图,如果顶点 (V) 可分割为两个互不相交的子集 ((A,B)) ,并且图中的每条边 ((i,j)) 所关联的两个顶点 (i)(j) 分别属于这两个不同的顶点集 ((i in A,j in B)),则称图 (G) 为一个二分图。
    • 匹配:满足其中任意两条边都没有公共顶点的边集
    • 最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。

    简介

    匈牙利算法用于求二分图的最大匹配
    模板题传送门:https://www.acwing.com/problem/content/description/863/

    步骤

    我们拿经典的男女配对来解释一下流程。

    情境:给出 (n_1) 个男生, (n_2) 个女生,他们如果之间连边则代表着他们之间相互喜欢(不考虑同性恋(故保证是二分图))。

    左边是男生,右边是女生。
    一号男生和一、二号女生相互喜欢,二号男生和二、三号女生相互喜欢,三号男生和三号女生相互喜欢。

    对于一号男生:
    他和二号女生互相喜欢(假设他在找女友的时候优先遍历到二号女生),而二号女生现在没有男友,配对成功,返回。

    对于二号男生:
    他和三号女生互相喜欢(假设他在找女友的时候优先遍历到三号女生),而三号女生现在没有男友,配对成功,返回。

    目前配对状况:

    对于三号男生:
    他和三号女生互相喜欢,但是此时三号女生有男友(二号)了,所以他标记了一下三号女生,然后去找到二号男生问他你能不能再去找一个其他女友?),然后二号男生就去遍历他的女友,发现三号已经被标记了,但二号没有标记,但是此时二号女生有男友(一号)了,所以二号男生就标记了二号女生,类似于三号男生的行为,然后去找到一号男生问他你能不能再去找一个其他女友,一号男生也开始遍历自己的女友,最后发现一号女生没有标记,于是配对成功。

    代码实现:
    我们规定:

    vis[i]=true 表示 i 号女生被标记,否则没有
    match[i]=j 表示 i 号女生的男友是 j 号,如果没有男友则默认是 0
    

    完整代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=505;
    int n1,n2,m;
    
    int h[N],tot;
    struct node{
    	int to,next;
    }e[N*N];
    void add(int u,int v){e[tot].to=v, e[tot].next=h[u], h[u]=tot++;}
    
    int match[N];
    bool vis[N];
    
    bool find(int x){
    	for(int i=h[x];~i;i=e[i].next){
    		int go=e[i].to;
    		if(!vis[go]){
    			vis[go]=true;
    			if(!match[go] || find(match[go])){
    				match[go]=x;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    int main(){
    	memset(h,-1,sizeof h);
    	cin>>n1>>n2>>m;
    	while(m--){
    		int u,v; cin>>u>>v;
    		add(u,v);
    	}
    	
    	int res=0;
    	for(int i=1;i<=n1;i++){
    		memset(vis,false,sizeof vis);
    		if(find(i)) res++;
    	}
    	cout<<res<<endl;
    	
    	return 0;
    }
    
  • 相关阅读:
    mysql无法启动-You may have to recover from a backup
    mysql导出索引sql 导出索引创建语句
    Padavan路由器设置桥接多路由器同WIFI方法
    挖的坑还是要填的
    I'm Back
    40行加速头文件
    一些XJOI博客的密码
    p进制线性基填坑
    Dirichelet卷积的k次方根
    用pb_ds写一颗线段树
  • 原文地址:https://www.cnblogs.com/Tenshi/p/14565488.html
Copyright © 2011-2022 走看看