zoukankan      html  css  js  c++  java
  • 洛谷 P3386 【模板】二分图匹配

    题目背景

    二分图

    题目描述

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

    输入输出格式

    输入格式:

    第一行,n,m,e

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

    输出格式:

    共一行,二分图最大匹配

    输入输出样例

    输入样例#1:
    1 1 1
    1 1
    输出样例#1:
    1

    说明

    n,m<=1000,1<=u<=n,1<=v<=m

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

    算法:二分图匹配

    网络流 最大流

    Dinic水过

    RE了无数次

    一定开大数组!!

    屠龙宝刀点击就送

    #include <cstdio>
    #include <queue>
    using namespace std;
    #define Max 1000000
    #define inf 1e9
    struct edge
    {
        int to,next,dis;
    }edge[Max*5];
    int ans,head[Max*5],cnt=1,dep[Max*2],n,m,e;
    void add(int u,int v,int l)
    {
        edge[++cnt].next=head[u];
        edge[cnt].to=v;
        edge[cnt].dis=l;
        head[u]=cnt;
    }
    bool bfs(int s,int t)
    {
        queue<int>q;
        for(int i=s;i<=t;++i) dep[i]=inf;
        dep[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int tp=q.front();
            q.pop();
            for(int i=head[tp];i;i=edge[i].next)
            {
                if(dep[edge[i].to]>dep[tp]&&edge[i].dis>0)
                {
                    dep[edge[i].to]=dep[tp]+1;
                    if(edge[i].to==t) return 1;
                    q.push(edge[i].to);
                }
            }
        }
        return 0;
    }
    int dfs(int now,int t,int came_flow)
    {
        if(now==t||came_flow<=0) return came_flow;
        int res=0,f;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(dep[edge[i].to]==dep[now]+1&&edge[i].dis>0&&(f=dfs(edge[i].to,t,min(edge[i].dis,came_flow))))
            {
                edge[i].dis-=f;
                edge[i^1].dis+=f;
                res+=f;
                came_flow-=f;
                if(came_flow<=0) break;
            }
        }
        return res;
    }
    int dinic(int s,int t)
    {
        while(bfs(s,t)) ans+=dfs(s,t,inf);
        return ans;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&e);
        for(int u,v;e--;)
        {
            scanf("%d%d",&u,&v);
            if(u<=n&&v<=m)
            {
                add(u,v+n,1);
                add(v+n,u,0);
            }
        }
        for(int i=1;i<=n;++i)
        add(0,i,1),add(i,0,0);
        for(int i=n+1;i<=m+n;++i)
        add(i,m+n+1,1),add(m+n+1,i,0);
        printf("%d",dinic(0,m+n+1));
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    Apache Kafka:下一代分布式消息系统
    深入理解Java之线程池
    JAVA中线程同步的方法(7种)汇总
    String、StringBuffer与StringBuilder之间区别
    Java中是否可以继承String类,为什么
    JAVA4种线程池的使用
    一分钟教你知道乐观锁和悲观锁的区别
    java常见面试题及答案 11-20(JVM)
    springmvc中的页面解析器ViewResolver不起作用,变量输出字符串的解决方案
    SpringMVC默认欢迎页面的问题
  • 原文地址:https://www.cnblogs.com/ruojisun/p/6653149.html
Copyright © 2011-2022 走看看