網絡流之最大流,Ford-Fulkerson方法

過程:
f(e):e上已流過的流量
c(e):e上允許流過的最大流量
殘餘網絡:f(e)小於c(e)的邊e && 滿足f(e)>0的e對應的反向邊rev(e)組成的網絡
增廣路:殘餘網絡上的s–>t路徑
求解最大流:就是不斷找圖中的增廣路,每找到一條,更新一次增廣路上的各邊的流量及其反向邊的流量。

crap:寒假以來學的第一個算法,也用它a了寒假的第一道題。
現在的話,有多想就有多害怕。未來如果失敗,有多想就會有多遺憾;如果成功,有多想就會有多開心。那就盡情去害怕,盡情遺憾盡情開心吧,反正我還年輕,浪擲幾年無所謂。我甘願用一生的時間去鑽研的東西也很多,不只去到那裏才能實現我想過的生活。而且,我不信我會淪落到困苦的田地。

板子:


public class Main {
	static int MAX_V=220,INF=10000010;
	static ArrayList<edge> G[]=new ArrayList[MAX_V];//鄰接表存圖
	static boolean used[]=new boolean[MAX_V];
	
	//向圖中添加邊
	static void add_edge(int from,int to,int cap) {
		G[from].add(new edge(to,cap,G[to].size()));
		G[to].add(new edge(from,0,G[from].size()-1));
	}
	
	//DFS尋找圖中增廣路
	//v爲當前所在點,t爲終點,f爲當前的流量
	static int dfs(int f,int v,int t) {
		if(v==t) {
			return f;
		}
		used[v]=true;
		edge e;
		for(int i=0;i<G[v].size();i++) {
			e=G[v].get(i);
			if(e.cap>0&&!used[e.to]) {
				int d=dfs(Math.min(f, e.cap),e.to,t);
				if(d>0) {
					//e的cap-=d
					e.cap-=d;
					//e的反向邊的cap+=d
					G[e.to].get(e.rev).cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	
	//求解從S到t的最大流
	static int max_flow(int s,int t) {
		int flow=0;
		for(;;) {
			for(int i=0;i<MAX_V;i++) {
				used[i]=false;
			}
			int f=dfs(INF,s,t);
			if(f==0) {
				return flow;
			}
			flow+=f;
		}
	}
	public static void main(String args[]) throws IOException{
		PrintWriter out=new PrintWriter(System.out);
		InputReader sc=new InputReader(System.in);
		while(true) {
			int N=sc.nextInt();
			int M=sc.nextInt();
			int u,v,c;
			for(int i=1;i<=M;i++) {
				G[i]=new ArrayList<edge>();
			}
			for(int i=0;i<N;i++) {
				u=sc.nextInt();
				v=sc.nextInt();
				c=sc.nextInt();
				add_edge(u, v, c);
			}
			out.println(max_flow(1,M));
			out.flush();
		}
	}
}
class edge{
	int to,cap,rev;
	//to 爲該邊指向的點,cap爲該邊當前還剩的流量,rev爲這個邊的反向邊在G[to]中的下標。
	public edge(int to,int cap,int rev) {
		this.to=to;
		this.cap=cap;
		this.rev=rev;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章