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);
    }
  • 相关阅读:
    快速创建一个 Servlet 项目(1)
    快速创建一个 Servlet 项目(2)
    多级派生情况下派生类的构造函数
    最近看了点C++,分享一下我的进度吧!
    进程同步&进程间通信
    multiprocess模块
    进程
    网络编程之socket
    网络通信原理
    网络通信的流程 | 初始socket
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677162.html
Copyright © 2011-2022 走看看