Expm 10_2 实现Ford-Fulkerson算法,求出给定图中从源点s到汇点t的最大流,并输出最小割。

  1 package org.xiu68.exp.exp10;
  2 
  3 import java.util.ArrayDeque;
  4 import java.util.ArrayList;
  5 import java.util.Arrays;
  6 
  7 public class Exp10_2 {
  8     //实现Ford-Fulkerson算法,求出给定图中从源点s到汇点t的最大流,并输出最小割。
  9     public static void main(String[] args) {
 10         // TODO Auto-generated method stub
 11         int[][] c=new int[][]{
 12             {0,1,1,0},
 13             {0,0,1,1},
 14             {0,0,0,1},
 15             {0,0,0,0}
 16         };
 17         MGraph1 m1=new MGraph1(c);
 18         m1.fordFulkerson(0, 3);
 19 
 20         int[][] c1=new int[][]{
 21             {0,3,3,4,0,0,0},
 22             {0,0,0,0,2,0,0},
 23             {0,1,0,0,1,0,0},
 24             {0,0,0,0,0,5,0},
 25             {0,0,0,1,0,1,2},
 26             {0,0,0,0,0,0,5},
 27             {0,0,0,0,0,0,0}
 28         };
 29         MGraph1 m2=new MGraph1(c1);
 30         m2.fordFulkerson(0, 6);
 31     }
 32 }
 33 
 34 class MGraph1{
 35     private int[][] c;        //容量矩阵
 36     private int[][] e;        //残量矩阵
 37     private int[][] f;        //当前流矩阵
 38     private int vexNum;        //顶点数量
 39     
 40     public MGraph1(int[][] c){
 41         this.c=c;
 42         this.vexNum=c.length;
 43         this.e=new int[vexNum][vexNum];
 44         this.f=new int[vexNum][vexNum];
 45 
 46         //刚开始时残量矩阵等于容量矩阵
 47         for(int i=0;i<vexNum;i++){
 48             System.arraycopy(c[i], 0, e[i], 0, c[i].length);
 49         }
 50         
 51     }
 52     //fordFulkerson算法
 53     public void fordFulkerson(int s,int t){
 54         int[] route=new int[vexNum];    //s到t的路径数组,route[i]表示i的前一个顶点
 55         
 56         while(bfs(s,t,route)){             //若还能找到一条路径
 57             
 58             //寻找路径中流最小的边的大小(在残量矩阵中)
 59             int min=Integer.MAX_VALUE;
 60             int tail=t;
 61             int head=route[t];
 62 
 63             while(head!=-1){
 64                 if(e[head][tail]<min){
 65                     min=e[head][tail];
 66                 }
 67                 tail=head;
 68                 head=route[head];
 69             }        
 70             
 71             //更新当前流矩阵和残量矩阵
 72             int tail1=t;
 73             int head1=route[tail1];
 74             while(head1!=-1){
 75                 //更新当前流矩阵
 76                 if(c[head1][tail1]!=0){        
 77                     f[head1][tail1]+=min;        //容量矩阵中存在边,增加head1到tail1的流的大小为min
 78                 }else{
 79                     f[head1][tail1]-=min;        //容量矩阵中不存在边,撤销head1到tail1的流的大小为min
 80                 }
 81                 //更新残量矩阵
 82                 e[head1][tail1]-=min;            //head1到tail1的流量减少min
 83                 e[tail1][head1]+=min;            //tail1到head1的流量增加min
 84                 
 85                 tail1=head1;
 86                 head1=route[head1];
 87             }//while
 88             //route=new int[vexNum];
 89             Arrays.fill(route, 0);                 //初始化路径数组
 90         }//while 还能找到一条s到t的路径
 91         
 92         int maxFlow=0;
 93         for(int i=0;i<vexNum;i++)                //最大流为  当前流矩阵中  从s流出的量
 94             maxFlow+=f[s][i];
 95         System.out.println("最大流为:"+maxFlow);
 96         
 97         
 98         System.out.print("最小割为(集合S):");
 99         ArrayList<Integer> cut=cut(s);
100         for(int i=0;i<cut.size();i++)
101             System.out.print(cut.get(i)+" ");
102         System.out.println();
103         
104     }
105     
106     //广度优先搜索在残量图e中寻找s到t的路径
107     public boolean bfs(int s,int t,int[] route){
108         boolean[] visited=new boolean[vexNum];        //访问数组
109         visited[s]=true;
110         
111         ArrayDeque<Integer> queue=new ArrayDeque<>();
112         route[s]=-1;                                //设s的前一个顶点为-1
113         
114         for(int i=0;i<vexNum;i++){
115             if(e[s][i]!=0 && !visited[i]){            //在残量矩阵中s到i存在一条路径
116                 queue.add(i);
117                 route[i]=s;
118                 visited[i]=true;
119             }
120         }
121         
122         while(!queue.isEmpty()){
123             int middleVex=queue.poll();
124             if(middleVex==t){
125                 return true;
126             }else{
127                 for(int i=0;i<vexNum;i++){
128                     if(e[middleVex][i]!=0 && !visited[i]){
129                         queue.add(i);
130                         route[i]=middleVex;
131                         visited[i]=true;
132                     }
133                 }
134             }
135         }//while
136         return false;
137     }
138     
139     //求最小割
140     //在残量矩阵中,从s开始做一次搜索,从s能达到的所有的顶点都属于集合S
141     public ArrayList<Integer> cut(int s){
142         boolean[] visited=new boolean[vexNum];
143         ArrayList<Integer> cut=new ArrayList<>();    //保存最小割,集合S
144         dfs(visited,cut,s);
145         return cut;
146     }
147     //深度优先搜索
148     private void dfs(boolean[] visited,ArrayList<Integer> cut,int v){
149         cut.add(v);
150         visited[v]=true;    
151         for(int i=0;i<vexNum;i++){
152             if(e[v][i]!=0 && !visited[i]){
153                 dfs(visited,cut,i);
154             }
155         }
156     }
157 }
View Code
原文地址:https://www.cnblogs.com/xiu68/p/8043674.html