1. 程式人生 > 其它 >P3386 【模板】二分圖最大匹配

P3386 【模板】二分圖最大匹配

建立原點,向左部連容量為 \(1\) 的邊,二分圖上的邊容量為 \(1\),右部向匯點連容量為 \(1\) 的邊。
最大流即可。正確性顯然。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1005,INF=0x3f3f3f3f3f3f3f3f;
struct edge{
	int from,to,cap,flow;
	edge(){
	}
	edge(int a,int b,int c,int d):from(a),to(b),cap(c),flow(d){
	}
};
struct Dinic{//net flow
	vector<edge> G;
	vector<int> e[maxn];
	int d[maxn],vis[maxn],cur[maxn];
	int s,t;
	int n,m;
	void addedge(int f,int t,int c){
		G.push_back((edge){f,t,c,0});
		G.push_back((edge){t,f,0,0});
		e[t].push_back(G.size()-1);
		e[f].push_back(G.size()-2);
	}
	bool BFS(){
		d[s]=0;
		memset(vis,0,sizeof(vis));
		queue<int> q;
		vis[s]=1;
		q.push(s);
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<e[u].size();i++){
				edge &k=G[e[u][i]];
				if(!vis[k.to]&&k.cap>k.flow){
					q.push(k.to);
					vis[k.to]=1;
					d[k.to]=d[u]+1;
				}
			}
		}
		return vis[t];
	}
	int DFS(int u,int lst){
		if(u==t||lst==0)return lst;
		int flow=0,f;
		for(int &i=cur[u];i<e[u].size();i++){
			edge &k=G[e[u][i]];
			if(d[k.to]==d[k.from]+1&&(f=DFS(k.to,min(lst,k.cap-k.flow)))>0){
				k.flow+=f;
				flow+=f;
				lst-=f;
				G[e[u][i]^1].flow-=f;
				if(lst==0)break;
			}
		}
		return flow;
	}
	int flow(){
		int F=0,res=0;
		while(BFS()){
			memset(cur,0,sizeof(cur));
			res+=DFS(s,INF);
		}
		return res;
	}
}D;
signed main(){
	int n,m;
    cin>>n>>m;
    D.n=n+m;cin>>D.m;
	for(int i=1;i<=D.m;i++){
		int u,v;
		cin>>u>>v;
		D.addedge(u,v+n,1);
	}
    for(int i=1;i<=n;i++)D.addedge(0,i,1);
    for(int i=1;i<=m;i++)D.addedge(i+n,D.n+1,1);
    D.s=0,D.t=D.n+1;
	cout<<D.flow();
	return 0;
}
YJX AK IOI