zoukankan      html  css  js  c++  java
  • 二分图匹配 (匈牙利算法) 洛谷3386

    题目背景

    二分图

    题目描述

    给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

    输入输出格式

    输入格式:
    第一行,n,m,e

    第二至e+1行,每行两个正整数u,v,表示u,v有一条连边

    输出格式:
    共一行,二分图最大匹配

    输入输出样例

    输入样例#1: 复制
    1 1 1
    1 1
    输出样例#1: 复制
    1
    说明

    n,m leq 1000 n,m≤1000 , 1 leq u leq n 1≤u≤n , 1 leq v leq m 1≤v≤m

    因为数据有坑,可能会遇到 v>mv>m 的情况。请把 v>mv>m 的数据自觉过滤掉。

    算法:二分图匹配

    其算法本质就是求增广路,用递归。整体上是一个贪心。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1000010;
    int n,m,e,match[maxn];    //match数组表示每个右部点所匹配的左部点。
    bool used[maxn];       //used数组表示是否到达过,每次遍历一个点时都要memset。
    struct Edge{
        int next,to;
    }edge[maxn];
    int head[maxn],cnt,ans;
    void add(int bg,int ed){
        edge[++cnt].to=ed;
        edge[cnt].next=head[bg];
        head[bg]=cnt;
    }
    inline bool dfs(int x){
        for(register int i=head[x];i;i=edge[i].next){
            int u=edge[i].to;
            if(!used[u]){
                used[u]=1;
                if(!match[u] || dfs(match[u])){    //如果此右部点没有匹配的左部点或右部点可以更换其他左部点。
                    match[u]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&e);
        for(register int i=1;i<=e;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            if(b>m || a>n)  continue;
            add(a,b);     //因为要遍历二分图的左部点,所以向右连边,不能视为无向图。
        }
        for(register int i=1;i<=n;i++){
            memset(used,false,sizeof(used));
            if(dfs(i)) ans++;
        }
        printf("%d",ans);
    }
  • 相关阅读:
    原生JS中apply()方法的一个值得注意的用法
    关于“float”的一次探索--遇到了一个span元素可以设置宽高引发的思考
    git常用命令
    react 项目全家桶构件流程
    vue回顶部 组件 可以直接使用
    vscode左边侧边栏字体的大小
    小程序的福音,
    Android实战技巧:Dialog (转)
    给Android 应用开发者的十个建议(转)
    多线程与异步的区别(转)
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677162.html
Copyright © 2011-2022 走看看