最大流
package 算法課程實驗;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**@author : fjl2401 創建時間:2017年12月17日 下午1:37:09
demo:1 maxvalue:50
4 5
1 2 40
2 3 30
1 4 20
3 4 10
2 4 20
1 4
demo:2 maxvalue:19
7 9
1 2 10
2 3 2
1 3 10
2 4 4
2 5 8
5 4 6
5 7 10
4 7 10
3 5 9
*/
public class Six {
int flag[];
int last[];
int Graph[][];
int from;
int to;
public Six() {
Graph=input();
}
public int [][] input(){
int a[][];
//input
System.out.println("請輸入圖的節點數和插入的邊數,用逗號隔開");
Scanner scanner=new Scanner(System.in);
String xString=scanner.nextLine();
String string[]=xString.split(" ");
//n邊數目,num節點數
int num=Integer.parseInt(string[0]);
int n=Integer.parseInt(string[1]);
a=new int[num+1][num+1];
//初始化
for (int i = 0; i < a.length; i++) {
for (int j = 0; j <a.length; j++) {
a[i][j]=-1;
}
}
System.out.println("請輸入起點,終點,權重,用空格隔開");
for (int i = 0; i <n; i++) {
String sd=scanner.nextLine();
String sds[]=sd.split(" ");
a[Integer.parseInt(sds[0])][Integer.parseInt(sds[1])]=Integer.parseInt(sds[2]);
}
System.out.println("請輸入源點和匯點,用空格隔開");
String sdString=scanner.nextLine();
String sources[]=sdString.split(" ");
from=Integer.parseInt(sources[0]);
to=Integer.parseInt(sources[1]);
scanner.close();
flag=new int [a.length];
last=new int [a.length];//上一個點
return a;
}
//bfs搜索道路
Boolean Search(int source,int t){
//初始化距離和顏色
for (int i = 0; i < Graph.length; i++) {
flag[i]=0;
last[i]=-1;
}
Queue<Integer> aQueue=new LinkedList<>();
//將初始點加入隊列
aQueue.add(source);
last[source]=-1;
flag[source]=1;
while(!aQueue.isEmpty()){
int lable=aQueue.remove();
for (int i = 0; i < Graph.length; i++) {
if (Graph[lable][i]>0&&flag[i]==0) {
flag[i]=1;
last[i]=lable;
if (i==t) {
return true;
}
aQueue.add(i);
}
}
}
return false;
}
//輸出圖
public void output(){
for (int i = 1; i < Graph.length; i++) {
for (int j = 1; j < Graph.length; j++) {
System.out.print(Graph[i][j]+" ");
}
System.out.println();
}
}
int EK() {
int allValue=0;
for (int i = 0; i < Graph.length; i++) {
for (int j = 0; j < Graph.length; j++) {
if (Graph[i][j]!=-1&&Graph[i][j]!=0) {
Graph[j][i]=0;
}
}
}
while(Search(from, to)) {
int minvalue=10000;
//找出這條bfs出來的道路上的最大容量
for (int j =to; j!=from; j=last[j]) {
minvalue=min(minvalue, Graph[last[j]][j]);
}
allValue+=minvalue;
//給這條路上的所有邊減掉最大容量,同時給反向邊增加容量
for (int i =to; i!=from; i=last[i]) {
Graph[last[i]][i]-=minvalue;
Graph[i][last[i]]+=minvalue;
}
}
return allValue;
}
int min(int i,int j) {
if (i>j) {
return j;
}
else {
return i;
}
}
public static void main(String[] args) {
Six a=new Six();
int weight=a.EK();
System.out.println(weight);
}
}
思想 :
用while循環 dfs找出剩餘網絡,找出dfs路徑可承受的最大流量,減去最大流,同時反向邊增加最大流,反向邊的容量減少代表着正向邊容量的增加。 相當於給了正向邊一個返回的機會。