匈牙利算法解无边权二分图最大匹配 入门教程

基本理论推荐阅读

目录

先贴个板子

#include<bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int maxe = 50005;

int n,m,e;
int ct,hed[maxn],ver[maxe],nt[maxe];
void ad(int a,int b) {
    ver[++ct]=b, nt[ct]=hed[a], hed[a]=ct;
}

int mc[maxn], vis[maxn];
bool dfs(int x) {
    for(int i=hed[x],y;i;i=nt[i]) if(!vis[y=ver[i]]) {
        vis[y]=1;
        if(!mc[y]||dfs(mc[y])) { //找到增广路
            mc[y]=x;
            return true;
        }
    }
    return false;
}

int main()
{
    scanf("%d%d%d", &n,&m,&e);
    for(int i=0,x,y;i<e;++i) {
        scanf("%d%d", &x,&y), ad(x,y);
    }
    int ans = 0;
    for(int i=1;i<=n;++i) {
        memset(vis,0,sizeof vis);
        if(dfs(i)) ++ans;
        //找到一条增广路并实施增广可以使最大匹配数加一
    }
    cout<<ans;
    return 0;
}

例题推荐

[ZJOI2007]矩阵游戏
发现无论怎么将一个有解的矩阵进行行列交换, 任意时刻其总是拥有 \(n\) 个黑点使得其行标号两两不同且其列标号两两不同。

连一连画一画发现就是个无边权二分图最大匹配的问题, 一侧是行, 另一侧是列, 一条边表示一个黑点。

贴下AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;

int n;

int ct,hed[maxn],ver[maxn*maxn],nt[maxn*maxn];
void ad(int a,int b) {
    ver[++ct]=b, nt[ct]=hed[a], hed[a]=ct;
}
int vis[maxn], mc[maxn];
bool dfs(int x) {
    for(int i=hed[x],y;i;i=nt[i]) if(!vis[y=ver[i]]) {
        vis[y]=1;
        if(!mc[y]||dfs(mc[y])) {
            mc[y]=x;
            return true;
        }
    }
    return false;
}

int main()
{
    int T; cin>>T; while(T--) {
        ct=0;
        memset(hed,0,sizeof hed);
        memset(mc,0,sizeof mc);
        scanf("%d", &n);
        for(int i=1,x;i<=n;++i) for(int j=1;j<=n;++j) {
            scanf("%d",&x); if(x) ad(i,j);
        }
        int ans = 0;
        for(int i=1;i<=n;++i) {
            memset(vis,0,sizeof vis);
            if(dfs(i)) ++ans;
        }
        if(ans==n) puts("Yes");
        else puts("No");
    }
    return 0;
}

棋盘覆盖
将棋盘奇偶分类(按行标列标之和的奇偶性分类每个格子)(也叫黑白染色)。
然后就可以二分图搞了, 注意建图的时候好好思考下细节。

贴下AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;

int n, t;
bool vis[maxn][maxn];

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int ct,hed[maxn*maxn],nt[maxn*maxn],ver[maxn*maxn];
void ad(int a,int b) {
    ver[++ct]=b,nt[ct]=hed[a],hed[a]=ct;
}

int v[maxn*maxn], mc[maxn*maxn];
bool dfs(int x) {
    for(int i=hed[x],y;i;i=nt[i]) if(!v[y=ver[i]]) {
        v[y]=1;
        if(!mc[y]||dfs(mc[y])) {
            mc[y]=x;
            return true;
        }
    }
    return false;
}
int main()
{
    scanf("%d%d", &n, &t);
    for(int i=0,x,y;i<t;++i) {
        scanf("%d%d", &x,&y); vis[x][y] = true;
    }
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j) if(!vis[i][j] && (i+j)&1) {
        for(int k=0;k<4;++k) {
            int x=i+dx[k], y=j+dy[k];
            if(x<1||x>n||y<1||y>n||vis[x][y]) continue;
            ad((i-1)*n+j, (x-1)*n+y);
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j) if(!vis[i][j] && (i+j)&1) {
        memset(v,0,sizeof v);
        if(dfs((i-1)*n+j)) ++ans;
    }
    cout<<ans;
    return 0;
}

車的放置
所有车的行标两两不同,列标两两不同。
剩下的就是和 [ZJOI2007矩阵游戏] 一样, 用边表示一个格子, 然后跑无边权二分图最大匹配就行了。
AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
int n,m,t;
bool vis[maxn][maxn];

int ct,hed[maxn],ver[maxn*maxn],nt[maxn*maxn];
void ad(int a,int b) {
    ver[++ct]=b, nt[ct]=hed[a], hed[a]=ct;
}

int mc[maxn], v[maxn];
bool dfs(int x) {
    for(int i=hed[x],y;i;i=nt[i]) if(!v[y=ver[i]]) {
        v[y]=1;
        if(!mc[y]||dfs(mc[y])) {
            mc[y]=x;
            return true;
        }
    }
    return false;
}
int main()
{
    scanf("%d%d%d", &n,&m,&t);
    for(int i=0,x,y;i<t;++i) {
        scanf("%d%d", &x,&y); vis[x][y]=1;
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            if(!vis[i][j]) ad(i,j);
    int ans=0;
    for(int i=1;i<=n;++i) {
        memset(v,0,sizeof v);
        if(dfs(i)) ++ans;
    }
    cout<<ans;
    return 0;
}

导弹防御塔
人菜,不会


蚂蚁
人菜,不会

原文链接: https://www.cnblogs.com/tztqwq/p/12810805.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    匈牙利算法解无边权二分图最大匹配 入门教程

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/345459

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午3:15
下一篇 2023年3月2日 上午3:16

相关推荐