洛谷P3386:網絡流之二分圖匹配,最大流算法

在這裏插入圖片描述
二分圖:我的理解是,對圖中的點集,可分爲兩個集合U和V,使得兩個集合之間存在通路,且集合內部不存在通路。如上圖。
匹配:兩兩不含公共端點的邊集合M
最大匹配:邊數最多的匹配
完美匹配:最大匹配的匹配數滿足2*M=點的總數
二分圖匹配:二分圖中的匹配

實際上,可將二分圖最大匹配問題看作是最大流問題的特殊情況。
在這裏插入圖片描述
最大流方法解決二分圖匹配:
將原圖中的所有無向邊e改爲有向邊,方向從U到V,容量爲1.增加原點s和匯點t,從s向所有的頂點u∈U連一條容量爲1的邊,從所有的頂點v∈V連一條容量爲1的邊。
ff方法解決二分圖匹配(洛谷p3386):
在這裏插入圖片描述


class Main{
	static int maxn=1010;
	static ArrayList<edge> G[]=new ArrayList[2*maxn];
	static boolean vis[]=new boolean[2*maxn];
	static class edge{
		int to,cap,rev;
		public edge(int to,int cap,int rev) {
			this.to=to;
			this.cap=cap;
			this.rev=rev;
		}
	}
	static boolean dfs(int v,int t){
		if(v==t){
			return true;
		}
		vis[v]=true;
		int u,cap,rev;
		for(int i=0;i<G[v].size();i++){
			u=G[v].get(i).to;
			cap=G[v].get(i).cap;
			rev=G[v].get(i).rev;
			if(!vis[u]&&cap>0&&dfs(u,t)){
				G[u].get(rev).cap++;
				G[v].get(i).cap--;
				return true;
			}
		}
		return false;
	}
	static void add_edge(int v,int u){
		G[v].add(new edge(u,1,G[u].size()));
		G[u].add(new edge(v,0,G[v].size()-1));
	}
	static int max_flow(int s,int t){
		int res=0;
		for(;;){
			for(int i=0;i<2*maxn;i++) {
				vis[i]=false;
			}
			if(dfs(s,t)) {
				res++;
			}else {
				break;
			}
		}
		return res;
	}
	public static void main(String args[]){
		InputReader sc=new InputReader(System.in);
		PrintWriter out =new PrintWriter(System.out);
		
		int n=sc.nextInt();
		int m=sc.nextInt();
		int e=sc.nextInt();
		for(int i=1;i<=n+m+10;i++) {
			G[i]=new ArrayList<>();
		}
		int u,v;
		for(int i=0;i<e;i++) {
			u=sc.nextInt();
			v=sc.nextInt();
			if(v<=m&&u<=n) {
				add_edge(u, v+n);
			}
		}
		int s=n+m+1;
		int t=s+1;
		G[s]=new ArrayList<edge>();
		G[t]=new ArrayList<edge>();
		for(int i=1;i<=n;i++) {
			add_edge(s, i);
		}
		for(int i=n+1;i<=n+m;i++) {
			add_edge(i, t);
		}
		out.println(max_flow(s,t));
		out.flush();
		out.close();
	}
}
發佈了76 篇原創文章 · 獲贊 3 · 訪問量 3942
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章