网络流之最大流,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;
	}
}


发布了73 篇原创文章 · 获赞 3 · 访问量 3502

猜你喜欢

转载自blog.csdn.net/qq_42021845/article/details/104008552