二分图最大匹配[网络流]

题目背景

二分图

题目描述

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

输入输出格式

输入格式:

第一行,n,m,e

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

输出格式:

共一行,二分图最大匹配



建模:

s--1-->X--1-->Y--1-->t

注意:边的数量

PS:本题比hungary快了5倍

//
//  main.cpp
//  二分图dinic
//
//  Created by Candy on 29/11/2016.
//  Copyright © 2016 Candy. All rights reserved.
//

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2005,M=1e6,INF=1e9;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,m,k,s,t,u,v;
struct edge{
    int v,ne,c,f;
}e[M<<1];
int cnt,h[N];
inline void ins(int u,int v,int c){
    cnt++;
    e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
}
int vis[N],d[N],q[N],head=1,tail=1;
bool bfs(){
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
    head=tail=1;
    q[tail++]=s;d[s]=0;vis[s]=1;
    while(head!=tail){
        int u=q[head++];
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]&&e[i].c>e[i].f){
                vis[v]=1;d[v]=d[u]+1;
                q[tail++]=v;
                if(v==t) return true;
            }
        }
    }
    return false;
}
int cur[N];
int dfs(int u,int a){
    if(u==t||a==0) return a;
    int flow=0,f;
    for(int &i=cur[u];i;i=e[i].ne){
        int v=e[i].v;
        if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c-e[i].f)))>0){
            flow+=f;
            e[i].f+=f;
            e[((i-1)^1)+1].f-=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}
int dinic(){
    int flow=0;
    while(bfs()){
        for(int i=s;i<=t;i++) cur[i]=h[i];
        flow+=dfs(s,INF);
    }
    return flow;
}
int main(int argc, const char * argv[]) {
    n=read();m=read();k=read();s=0;t=n+m+1;
    while(k--){
        u=read();v=read();
        if(v>m||u>n)continue;
        ins(u,n+v,1);
    }
    for(int i=1;i<=n;i++) ins(s,i,1);
    for(int i=1;i<=m;i++) ins(n+i,t,1);
    int ans=dinic();
    printf("%d",ans);
    return 0;
}
时间: 2024-12-25 17:25:15

二分图最大匹配[网络流]的相关文章

dinic求解二分图最大匹配&amp;&amp;网络流24题之飞行员配对方案问题

在二分图的基础上增加源S和汇T.1.S向X集合中每个顶点连一条容量为1的有向边.2.Y集合中每个顶点向T连一条容量为1的有向边.3.XY集合之间的边都设为从A集合中的点到B集合之中的点,容量为1的有向边. 求网络最大流,流量就是匹配数,所有满流边是一组可行解. 所以就解决了. 飞行员配对方案问题: 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外

【网络流-二分图最大匹配】poj3041Asteroids

/* 这道题将每行x看成是结点x,没列y看成是结点y,而障碍物的坐标xy看成是从x到y的 一条边.建图后问题就变成了,找最少的点,使得这些点与所有的边相邻,即最小 点覆盖,用匈牙利算法解决. ------------------------------- 定理:最小点覆盖数 = 最大匹配数,即求图的最大匹配即可,匈牙利算法 ------------------------------- 模板讲解: bool find(int v) { for(int i=1; i<=n; i++) { if(g

二分图与网络流 带权二分图的最大匹配

二分图与网络流  带权二分图的最大匹配 在某书上偶然发现,二分图和网络流是有联系的,在子图u中建立超级源点,在子图v中建立超级汇点,源点到u和汇点到v的每条边容量设为1,u和v中的边的容量也设为1,求出最大流也就是原二分图的最大匹配了. 而求带权二分图的最大匹配也就很容易了,将u和v的权值设为容量,仍然建立超级源点和超级汇点转为网络流解决即可. 真是一切皆可网络流啊...

【网络流#6】POJ 3041 Asteroids 二分图最大匹配 - 《挑战程序设计竞赛》例题

学习网络流中ing...作为初学者练习是不可少的~~~构图方法因为书上很详细了,所以就简单说一说 把光束作为图的顶点,小行星当做连接顶点的边,建图,由于 最小顶点覆盖 等于 二分图最大匹配 ,因此求二分图最大匹配即可. 邻接矩阵,DFS寻找增广路,匈牙利算法 邻接矩阵:复杂度O(n^3) 如果使用邻接表:复杂度O(n*m) #include<cstdio> #include<cstring> #include<cmath> #include<iostream>

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

网络流之二分图最大匹配

前言:二分图最大匹配往往用于普通的指派问题中,可转换为最大流问题求解,也可以利用二分图的性质及其边的容量为1的特点,简单的实现二分图的最大匹配算法. 问题模型:有n台计算机和k个任务,每台计算机处理的任务种类不同,问如果给每台计算机分配一个任务,一次最多能处理多少个任务. 分析:该问题可以转化为图论模型来分析.设U为所有计算机顶点的集合,V为所有任务类型的集合,u属于U,v属于V,e=(u,v)表示计算机u能处理任务v,E是所有e的集合. 则G=(U||V, E),且G中满足两两不含公共端点的边

51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左边的点和没用过的右边的点连起来, 如果遇到一个点已经连过就试着把原来的拆掉 把现在这条线连起来看能不能多连上一条线. 总结来说就是试和拆,试的过程很简单,拆的过程由于使用递归写的,很复杂.很难讲清楚,只能看代码自己理会. 代码(有注释): #include <bits\stdc++.h> usin

Codevs1232飞行员配对方案问题【二分图最大匹配】

Codevs上的Special Judge似乎挂了 所以就跑到COGS上交 http://cojs.tk/cogs/problem/problem.php?pid=14 14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题

二分图、网络流模版总结

这个星期重新回去理解二分图和网络流的算法,觉得当初真的是有点傻萌,都不太了解就直接套模版…… 关于二分图 关于二分图的概念不想吐槽了,太多而且好多都好乱,看了很多个什么概念总结结果发现有的人把最大匹配叫最佳匹配.反正是看的我一脸蛋疼,决定还是抛开概念吧,看着像啥用啥得了. 匈牙利算法: 其实就是不断寻找增广路.那么什么是增广路呢? 既然是二分图,我们先定义X集和Y集.然后我们对X集里面的点一个一个来,拿出一个没用过的X集的点(简记为i),找所有和它相连的Y集的点(简记为j),如果这个Y集的点没用