图论训练之十四

复习一下网络流二分图

https://www.luogu.org/problem/P3386

分析:没什么好分析的.......

因为没学过匈牙利算法,所以就打一个网络流

建一个超级源点和一个超级汇点

此时最大匹配=最大流

code by wzxbeliever:

#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ri register int
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=2005;
const int maxm=1002005;
const int inf=0x7fffffff;
struct node{
	int to,next,w;
}edg[maxm<<1];
int cnt,n,m,S,T,x,y,k;
int dp[maxn],head[maxn];
queue<int>Q;
il void add(int u,int v,int w){
	cnt++;
	edg[cnt].next=head[u];
	edg[cnt].to=v;
	edg[cnt].w=w;
	head[u]=cnt;
}
il bool bfs(){
	while(!Q.empty())Q.pop();
	memset(dp,0,sizeof(dp));
	dp[S]=1;Q.push(S);
	while(!Q.empty()){
		int u=Q.front();Q.pop();
		for(ri i=head[u];i;i=edg[i].next){
			int to=edg[i].to;
			if(!dp[to]&&edg[i].w>0)dp[to]=dp[u]+1,Q.push(to);
		}
	}
	return dp[T];
}
il int dfs(int u,int flow){
	if(u==T)return flow;
	int re=flow,k;
	for(ri i=head[u];i;i=edg[i].next){
		int to=edg[i].to;
		if(edg[i].w>0&&dp[to]==dp[u]+1&&re>0){
			k=dfs(to,min(edg[i].w,re));
			if(k>0)
			edg[i].w-=k,edg[i^1].w+=k,re-=k;
		}
	}
	return flow-re;
}
il int dinic(){
	int ans=0;
	while(bfs())ans+=dfs(S,inf);
	return ans;
}
int main(){
	scanf("%d%d%d",&x,&y,&k);
	n=x+y+2;
	for(ri i=1,u,v;i<=k;i++){
		scanf("%d%d",&u,&v);
		if(u<=x&&v<=y)
		add(u+1,v+x+1,1),add(v+x+1,u+1,0);
	}
	for(ri i=1;i<=x;i++)add(1,i+1,1),add(i+1,1,0);
	for(ri i=1;i<=y;i++)add(i+x+1,n,1),add(n,i+x+1,0);
	S=1,T=n;
	printf("%d\n",dinic()); 
	return 0;
}

posted @ 2019-10-29 20:05  wzx_believer  阅读(99)  评论(0编辑  收藏  举报