搜索与图论:匈牙利算法

将所有点分成两个集合,使得所有边只出现在集合之间,就是二分图

二分图:一定不含有奇数个点数的环;可能包含长度为偶数的环, 不一定是连通图

二分图的最大匹配:

cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 510 , M = 100010;
int n1,n2,m;
int h[N],ne[M],e[M],idx;//邻接表
bool st[N];
int match[N];

void add(int a , int b)
{//头插法
    //如图 如1与2之间要有一条线,让2的ne为1,再让h[1]为2的索引。
    //这样h[1]就是1节点存的最后一个相连的点,如图就是7节点。
    //而在索引表内部,通过头插法的方式(即每次ne指向上一个点(h存的就是上一个点)),索引表为:7->4->2
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int find(int x)
{
    //遍历自己喜欢的女孩
    for(int i = h[x] ; i != -1 ;i = ne[i])
    {
        int j = e[i];
        if(!st[j])//如果在这一轮模拟匹配中,这个女孩尚未被预定
        {
            st[j] = true;//那x就预定这个女孩了,这里预定是防止她男朋友找其他喜欢的女孩时不重复找这个
            //如果女孩j没有男朋友,或者她原来的男朋友能够预定其它喜欢的女孩。配对成功
            if(!match[j]||find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }
    //自己中意的全部都被预定了。配对失败。
    return false;
}

int main()
{
    memset(h,-1,sizeof h);
    scanf("%d%d%d",&n1,&n2,&m);
    while(m--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
    }

    int res = 0;
    for(int i = 1; i <= n1 ;i ++)
    {  
        //因为每次模拟匹配的预定情况都是不一样的所以每轮模拟都要初始化
        memset(st,false,sizeof st);
        if(find(i)) res++;//找到一条边,则res++
    }  

    printf("%d\n",res);
}
相关推荐
2501_9411116810 小时前
模板编译期哈希计算
开发语言·c++·算法
CoovallyAIHub10 小时前
智能体与小模型:AI迈向平民化的新浪潮
深度学习·算法·计算机视觉
jllllyuz10 小时前
基于粒子群优化(PSO)的特征选择与支持向量机(SVM)分类
开发语言·算法·matlab
啊吧怪不啊吧11 小时前
贪心算法(局部最优实现全局最优)第一篇
算法·贪心算法
Yue丶越11 小时前
【C语言】深入理解指针(四)
java·c语言·算法
Abona12 小时前
自动驾驶、无人机、机器人核心技术双范式
算法·机器人·自动驾驶·无人机
草莓熊Lotso12 小时前
《算法闯关指南:优选算法--模拟》--39.替换所有问号,40.提莫攻击
开发语言·c++·算法·模拟
草莓熊Lotso13 小时前
C++ STL set 系列完全指南:从底层原理、核心接口到实战场景
开发语言·c++·人工智能·经验分享·网络协议·算法·dubbo
做怪小疯子15 小时前
LeetCode 热题 100——子串——和为 K 的子数组
算法·leetcode·职场和发展
zl_vslam16 小时前
SLAM中的非线性优-3D图优化之李群李代数在Opencv-PNP中的应用(四)
人工智能·opencv·算法·计算机视觉