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 }