1. 程式人生 > >P3386 【模板】二分圖匹配 -網絡流

P3386 【模板】二分圖匹配 -網絡流

二分圖最大匹配 兩個 遇到 tin 思路 otto ext void copy

            二分圖匹配

題目背景

二分圖

感謝@一扶蘇一 提供的hack數據

題目描述

給定一個二分圖,結點個數分別為n,m,邊數為e,求二分圖最大匹配數

輸入輸出格式

輸入格式:

第一行,n,m,e

第二至e+1行,每行兩個正整數u,v,表示u,v有一條連邊

輸出格式:

共一行,二分圖最大匹配

輸入輸出樣例

輸入樣例#1: 復制
1 1 1
1 1
輸出樣例#1: 復制
1

說明

n,m \leq 1000n,m1000 , 1 \leq u \leq n1un , 1 \leq v \leq m1vm

因為數據有坑,可能會遇到 v>mv>m 的情況。請把 v>mv>m 的數據自覺過濾掉。

算法:二分圖匹配

思路


dinic跑二分圖最大流

一個源點(0)連接1到n

一個匯點(n+m+1)連接n+1到n+m

套上板子就可以了


 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #define inf 0x3f3f3f3f
 6 #define maxn 2010001
 7
using namespace std; 8 9 int n,m,s,t; 10 struct node{ 11 int v,next,cap; 12 }e[maxn]; 13 int head[maxn],tot=1; 14 int dis[maxn]; 15 16 void add_node(int a,int b,int c) 17 { 18 e[++tot]=(node){b,head[a],c}; 19 head[a]=tot; 20 } 21 22 bool bfs() 23 { 24 memset(dis,-1
,sizeof(dis)); 25 queue<int> q; 26 q.push(s); 27 dis[s]=0; 28 while(!q.empty()) { 29 int x=q.front(); 30 q.pop(); 31 for(int i=head[x];i;i=e[i].next) 32 { 33 int v=e[i].v; 34 if(e[i].cap&&dis[v]==-1) 35 { 36 dis[v]=dis[x]+1; 37 q.push(v); 38 } 39 } 40 } 41 return dis[t]!=-1; 42 } 43 44 int dfs(int now,int f) 45 { 46 if(now==t) return f; 47 int rest=f; 48 for(int i=head[now];i;i=e[i].next) 49 { 50 int v=e[i].v; 51 if(e[i].cap&&rest&&dis[v]==dis[now]+1) 52 { 53 int t=dfs(v,min(rest,e[i].cap)); 54 if(!t) dis[v]=0; 55 e[i].cap-=t; 56 e[i^1].cap+=t; 57 rest-=t; 58 } 59 } 60 return f-rest; 61 } 62 63 void dinic() 64 { 65 int ans=0; 66 while(bfs()) 67 ans+=dfs(s,inf); 68 printf("%d",ans); 69 } 70 71 int main() 72 { 73 int ee; 74 scanf("%d%d%d",&n,&m,&ee); 75 int x,y; 76 for(int i=1;i<=ee;++i) { 77 scanf("%d%d",&x,&y); 78 if(x>n||y>m) continue; 79 add_node(x,y+n,1); 80 add_node(y+n,x,0); 81 } 82 s=0;t=n+1+m; 83 for(int i=1;i<=n;++i) { 84 add_node(s,i,1); 85 add_node(i,s,0); 86 } 87 for(int i=1;i<=m;++i) { 88 add_node(n+i,t,1); 89 add_node(t,n+i,0); 90 } 91 dinic(); 92 return 0; 93 }

P3386 【模板】二分圖匹配 -網絡流