• P3386 【模板】二分图最大匹配 题解(匈牙利算法)


    题目连接

    题目思路

    如果不要去证明这个算法的正确性的话,我认为这只能算是一个简单贪心的dfs

    可能一直被它高深的名字骗了没有去深入学习

    时间复杂度\(O(nm)\) \(n\)代表点数,\(m\)代表边数

    算法流程大概是如下 参考洛谷的题解

    1.从任意一个没有被配对的点x开始,从点x的边中任意选一条边。如果此时点i没有被配对那么配对成功,则找到了一条增广路。如果点i此时已经被配对了,那么可以尝试将点match[i]与其他点配对。如果尝试成功,则找到一条增广路。这里用match[ ]来记录配对关系, 即match[i] = x。 并且将配对数+1。 这个过程我们用dfs来实现。

    2.如果配对失败,就从点x的边中重选一条边尝试。直到点x配对成功或尝试完x所有的边。

    3.接下来对没有配对的点一一进行配对,直到所有的点都尝试完毕找不到新的增广路。

    二分图染色好像能解决一堆覆盖问题,以后有机会再好好了解下吧

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=5e2+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,m,e;
    vector<int> g[maxn];
    bool vis[maxn];
    int match[maxn];
    bool dfs(int u){
        for(auto x:g[u]){
            if(vis[x]) continue;
            vis[x]=1;
            if(match[x]==-1||dfs(match[x])){
                match[x]=u;
                return 1;
            }
        }
        return 0;
    }
    signed main(){
       scanf("%d%d%d",&n,&m,&e);
       for(int i=1,u,v;i<=e;i++){
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
       }
       int ans=0;
       memset(match,-1,sizeof match);
       for(int i=1;i<=n;i++){
            memset(vis,0,sizeof vis);
            ans+=dfs(i);
       }
       printf("%d\n",ans);
        return 0;
    }
    
    
  • 相关阅读:
    数据库索引的作用和长处缺点
    ping不通的几种可能原因
    UVA
    strtok、strtok_s、strtok_r 字符串切割函数
    CheckBoxPreference组件
    EM算法原理
    Android中ExpandableListView控件基本使用
    拓扑排序的原理及事实上现
    DropdownList绑定的两种方法
    leetcode第一刷_Length of Last Word
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15950436.html
Copyright © 2020-2023  润新知