码迷,mamicode.com
首页 > 其他好文 > 详细

Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业

时间:2017-12-17 12:21:19      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:cli   []   nbsp   this   访问   https   i++   并且   hid   

技术分享图片

(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 }
View Code

 

Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业

标签:cli   []   nbsp   this   访问   https   i++   并且   hid   

原文地址:http://www.cnblogs.com/xiu68/p/8051505.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!