zoukankan      html  css  js  c++  java
  • 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 }
    View Code
  • 相关阅读:
    struts2.16 启动报错解决方案 at com.opensymphony.xwork2.util.FileManager$FileRevision.needsReloading(FileManager.java:209)
    多线程的概念
    JQuery Easy Ui 可装载组合框 ComboBox
    Spring 3.0 基于 Annotation 的依赖注入实现
    JQuery Easy Ui dataGrid 数据表格
    数据库中 对原有字段进行字符串追加处理
    1.Python知识点补充
    转跨站脚本攻击详解
    Wiz笔记
    ASP.NET角色管理的基本配置
  • 原文地址:https://www.cnblogs.com/xiu68/p/8051505.html
Copyright © 2011-2022 走看看