图论:二分图最大匹配(网络流最大流算法)

点击查看折叠代码块
/*
二分图最大匹配,网络流最大流 
左边为n个点,编号从 1---n
右边为m个点 编号从 n+1---n+m
建立超级源点0和超级汇点n+m+1 
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=510;
const int maxm=5e4+10;
const int inf=0x3f3f3f3f;
int head[maxn<<1],cnt=0;
int dis[maxn<<1];
struct edge{
	int v,next;
	int c;
}e[maxm<<3];

void add(int u,int v,int c){
	e[cnt].v=v;
	e[cnt].c=c;
	e[cnt].next=head[u];
	head[u]=cnt++;
}

int n,m,E;
int s=0,t;

void create_graph(){
	memset(head,-1,sizeof(head));
	cnt=0;
	
	cin>>n>>m>>E;
	t=n+m+1;
	for (int i=1;i<=E;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		v+=n;
		add(u,v,1);add(v,u,0);
	}
	for (int i=1;i<=n;i++){
		add(s,i,1);add(i,s,0);
	}
	for (int i=n+1;i<=n+m;i++){
		add(i,t,1);add(t,i,0);
	}
}

bool bfs(int s,int t){
	memset(dis,-1,sizeof(dis));
	dis[s]=0;
	queue<int>q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for (int i=head[u];~i;i=e[i].next){
			int v=e[i].v,c=e[i].c;
			if(c>0 && dis[v]==-1){
				dis[v]=dis[u]+1;
				q.push(v);
			}
		}
	}
	return dis[t]!=-1;
}

int dfs(int u,int flow){
	if(u==t) return flow;
	int delta =flow;
	for (int i=head[u];~i;i=e[i].next){
		int v=e[i].v,c=e[i].c;
		if(c>0 && dis[v]==dis[u]+1){
			int d=dfs(v,min(c,delta));
			if(d==0) dis[v]=0;
			e[i].c-=d;
			e[i^1].c+=d;
			delta-=d;
			if(delta == 0) break;
		}
	}
	return flow-delta;
}

int dinic(int s,int t){
	int maxflow = 0;
	while(bfs(s,t)){
		maxflow+=dfs(s,inf);
	}
	return maxflow;
}

int main(){
	create_graph();
	int ans = dinic(s,t);
	cout<<ans<<endl;
	return 0;
}
posted @ 2020-07-28 20:11  wsl_lld  阅读(402)  评论(0编辑  收藏  举报