Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业
Posted 薰衣草
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业相关的知识,希望对你有一定的参考价值。
(a) 利用ford-fulkerson算法即可求出最大流和最小分割。
(b) 剩余网络为
由S可达的顶点为A、B。可达T的顶点为C。
(c) 瓶颈边有e(A,C),e(B,C)。
(d) 下图中不包含瓶颈边。
(e) 如果一条边e(u,v)是瓶颈边,首先这条边必须存在原图中,同时,在残量图中存在S到u的路径并且存在v到T的路径,所以在残量图中增加一条边e(u,v)后将使最大流的规模增加。首先在残量图中从S开始进行一次DFS求出从源点S可以到达的顶点集合W,然后在残量图的反向图中从T开始进行DFS求出可以到达T的顶点集合Y。最后遍历原图中的所有边e(u,v),若uW并且vY,则e(u,v)是一条瓶颈边。
1 package org.xiu68.ch07.ex13; 2 3 import java.util.ArrayDeque; 4 import java.util.ArrayList; 5 import java.util.Arrays; 6 import java.util.HashSet; 7 import java.util.Iterator; 8 9 public class Ex7_17 { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 int[][] c=new int[][]{ 14 {0,7,6,0,0,0}, 15 {0,0,0,4,2,0}, 16 {0,0,0,2,3,0}, 17 {0,0,0,0,0,9}, 18 {0,0,0,0,0,5}, 19 {0,0,0,0,0,0} 20 }; 21 String[] vexs=new String[]{"S","A","B","C","D","T"}; 22 MGraph<String> m1=new MGraph<String>(c, vexs); 23 m1.fordFulkerson(0, 5); 24 } 25 26 } 27 28 class MGraph<T>{ 29 private int[][] c; //容量矩阵 30 private int[][] e; //残量矩阵 31 private int[][] f; //当前流矩阵 32 private int vexNum; //顶点数量 33 private String[] vexs; //顶点表 34 35 public MGraph(int[][] c,String[] vexs){ 36 this.c=c; 37 this.vexNum=c.length; 38 this.e=new int[vexNum][vexNum]; 39 this.f=new int[vexNum][vexNum]; 40 this.vexs=vexs; 41 42 //刚开始时残量矩阵等于容量矩阵 43 for(int i=0;i<vexNum;i++){ 44 System.arraycopy(c[i], 0, e[i], 0, c[i].length); 45 } 46 47 } 48 49 //fordFulkerson算法 50 public void fordFulkerson(int s,int t){ 51 int[] route=new int[vexNum]; //s到t的路径数组,route[i]表示i的前一个顶点 52 53 while(bfs(s,t,route)){ //若还能找到一条路径 54 55 //寻找路径中流最小的边的大小(在残量矩阵中) 56 int min=Integer.MAX_VALUE; 57 int tail=t; 58 int head=route[t]; 59 60 while(head!=-1){ 61 if(e[head][tail]<min){ 62 min=e[head][tail]; 63 } 64 tail=head; 65 head=route[head]; 66 } 67 68 //更新当前流矩阵和残量矩阵 69 int tail1=t; 70 int head1=route[tail1]; 71 while(head1!=-1){ 72 //更新当前流矩阵 73 if(c[head1][tail1]!=0){ 74 f[head1][tail1]+=min; //容量矩阵中存在边,增加head1到tail1的流的大小为min 75 }else{ 76 f[head1][tail1]-=min; //容量矩阵中不存在边,撤销head1到tail1的流的大小为min 77 } 78 //更新残量矩阵 79 e[head1][tail1]-=min; //head1到tail1的流量减少min 80 e[tail1][head1]+=min; //tail1到head1的流量增加min 81 82 tail1=head1; 83 head1=route[head1]; 84 }//while 85 //route=new int[vexNum]; 86 Arrays.fill(route, 0); //初始化路径数组 87 }//while 还能找到一条s到t的路径 88 89 //输出最大流 90 int maxFlow=0; 91 for(int i=0;i<vexNum;i++) //最大流为 当前流矩阵中 从s流出的量 92 maxFlow+=f[s][i]; 93 System.out.println("最大流为:"+maxFlow); 94 95 //输出最小割 96 System.out.print("最小割为(集合S):"); 97 HashSet<Integer> cut=cut(s); 98 for(Iterator<Integer> iter=cut.iterator();iter.hasNext();){ 99 System.out.print(vexs[iter.next()]+" "); 100 } 101 System.out.println(); 102 103 //输出瓶颈边 104 System.out.println("瓶颈边有"); 105 HashSet<Edge> bottleneckEdgeSet=bottleneckEdge(s,t); 106 for(Iterator<Edge> be=bottleneckEdgeSet.iterator();be.hasNext();){ 107 Edge ed=be.next(); 108 System.out.print("e("+vexs[ed.getHead()]+","+vexs[ed.getTail()]+") "); 109 } 110 } 111 112 //广度优先搜索在残量图e中寻找s到t的路径 113 public boolean bfs(int s,int t,int[] route){ 114 boolean[] visited=new boolean[vexNum]; //访问数组 115 visited[s]=true; 116 117 ArrayDeque<Integer> queue=new ArrayDeque<>(); 118 route[s]=-1; //设s的前一个顶点为-1 119 120 for(int i=0;i<vexNum;i++){ 121 if(e[s][i]!=0 && !visited[i]){ //在残量矩阵中s到i存在一条路径 122 queue.add(i); 123 route[i]=s; 124 visited[i]=true; 125 } 126 } 127 128 while(!queue.isEmpty()){ 129 int middleVex=queue.poll(); 130 if(middleVex==t){ 131 return true; 132 }else{ 133 for(int i=0;i<vexNum;i++){ 134 if(e[middleVex][i]!=0 && !visited[i]){ 135 queue.add(i); 136 route[i]=middleVex; 137 visited[i]=true; 138 } 139 } 140 } 141 }//while 142 return false; 143 } 144 145 //求最小割 146 //在残量矩阵中,从s开始做一次搜索,从s能达到的所有的顶点都属于集合S 147 public HashSet<Integer> cut(int s){ 148 boolean[] visited=new boolean[vexNum]; 149 HashSet<Integer> cut=new HashSet<>(); //保存最小割,集合S 150 dfs(e,visited,cut,s); 151 return cut; 152 } 153 //求瓶颈边 154 public HashSet<Edge> bottleneckEdge(int s,int t){ 155 156 HashSet<Integer> w=new HashSet<>(); //从顶点S可以到达的顶点集合 157 boolean[] visitedS=new boolean[vexNum]; 158 dfs(e,visitedS,w,s); //从顶点s开始进行深度优先搜索,求从顶点S可以到达的顶点集合 159 160 161 //求残量图的反向图 162 int[][] reverseE=new int[vexNum][vexNum]; 163 for(int i=0;i<vexNum;i++){ 164 for(int j=i+1;j<vexNum;j++){ 165 reverseE[i][j]=e[j][i]; 166 reverseE[j][i]=e[i][j]; 167 } 168 } 169 HashSet<Integer> y=new HashSet<>(); //从顶点S可以到达的顶点集合 170 boolean[] visitedT=new boolean[vexNum]; 171 dfs(reverseE,visitedT,y,t); //从顶点t开始进行深度优先搜索,求从顶点T可以到达的顶点集合 172 173 174 HashSet<Edge> bottleneckEdgeSet=new HashSet<>(); 175 //遍历原图中的所有边e(u,v),求u属于集合w,v属于集合y的边 176 for(int i=0;i<vexNum;i++){ 177 for(int j=0;j<vexNum;j++){ 178 if(c[i][j]!=0 && w.contains(i) && y.contains(j)){ 179 bottleneckEdgeSet.add(new Edge(i,j)); 180 } 181 } 182 } 183 return bottleneckEdgeSet; 184 } 185 //深度优先搜索,记录搜索到的所有顶点 186 private void dfs(int[][] edges,boolean[] visited,HashSet<Integer> set,int v){ 187 set.add(v); 188 visited[v]=true; 189 for(int i=0;i<vexNum;i++){ 190 if(edges[v][i]!=0 && !visited[i]){ 191 dfs(edges,visited,set,i); 192 } 193 } 194 } 195 } 196 197 class Edge{ 198 private int head; //边的头 199 private int tail; //边的尾 200 public Edge(int head, int tail) { 201 super(); 202 this.head = head; 203 this.tail = tail; 204 } 205 public int getHead() { 206 return head; 207 } 208 public void setHead(int head) { 209 this.head = head; 210 } 211 public int getTail() { 212 return tail; 213 } 214 public void setTail(int tail) { 215 this.tail = tail; 216 } 217 218 }
以上是关于Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业的主要内容,如果未能解决你的问题,请参考以下文章