圖的最大流算法--Edmonds-karp

最大流

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路徑可承受的最大流量,減去最大流,同時反向邊增加最大流,反向邊的容量減少代表着正向邊容量的增加。 相當於給了正向邊一個返回的機會。

PS:dfs的時候是對新圖進行搜索,也就是說對反向邊也進行搜索。

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