過程:
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;
}
}