[Maxflow Mincut] Coursera Maxflow Mincut 最大流最小割集

来源:互联网 发布:form.js 跨域上传文件 编辑:程序博客网 时间:2024/06/05 17:53

最近在忙项目,闲下来一天时间,继续学习Cousera上的Algorithm,这本大红书真是好用,比严某某的不知道高到那里去了,而且真心应该看英文原版。


最大流问题的本质在于寻找一条augmenting path form source to end,每找到一条augmenting path就可以使flow增加,所谓的augmenting path是一条从source 到end的无向路径,其中可以包含前向通路(forward path not full)和后向通路(backward path not empty),所以流程如下

  1. 利用BFS或者DFS或者最短路径算法 寻找一条送source到end的无向路径(undirected path)
  2. 检查该路径是否满足augmenting path的要求,如满足,则循路径方向increase forward path decrease backward path并寻找其中的瓶颈,
  3. 如此往复直到没有augmenting path 得出最后的Maxflow
  4. MinCut可以从Source出发,寻找与之相连并且forward path not full,backward path not empty的点即可

本次课程的编程作业是来计算棒球比赛赛程进行一段时间后,是否有球队因为成绩太差,无论后期如何,都会提前出局。

主要的思想在于建立一个剩余比赛的网络,然后求其最大流及相应割集,割集中的节点就是导致该响应队伍出局的原因。难点在于如何形成network,解MAxflow可以直接调用函数库

import edu.princeton.cs.algs4.Bag;import edu.princeton.cs.algs4.FlowEdge;import edu.princeton.cs.algs4.FlowNetwork;import edu.princeton.cs.algs4.FordFulkerson;import edu.princeton.cs.algs4.In;import edu.princeton.cs.algs4.ST;import edu.princeton.cs.algs4.StdOut;public class BaseballElimination {private final int[] w;private final int[] l;private final int[] r;private final int[][] g;private final ST<String, Integer> teams;private final ST<Integer,String> reverseInt;private final int N;private final boolean[] isElimated;private final Bag<String>[] subsets;@SuppressWarnings("unchecked")public BaseballElimination(String filename){// create a baseball division from given filename in format specified belowIn in = new In(filename);N = in.readInt();w = new int[N];l = new int[N];r = new int[N];reverseInt = new ST<Integer,String>();isElimated = new boolean[N];teams = new ST<String,Integer>();g = new int[N][N];subsets =  (Bag<String>[]) new Bag[N];        for (int q = 0; q < N; q++)            subsets[q] = new Bag<String>();int i = 0;while (!in.isEmpty()){String tmp = in.readString();teams.put(tmp,i);reverseInt.put(i,tmp);w[i] = in.readInt();l[i] = in.readInt();r[i] = in.readInt();for(int j = 0; j < N ; j++){g[i][j] = in.readInt();}i++;}for(int ii = 0; ii<N;ii++ ){int sum = w[ii] + r[ii];for(int m = 0; m < N; m++){if(sum < w[m]){isElimated[ii] = true;subsets[ii].add(reverseInt.get(m));}}}for(int index = 0;index < N; index ++){if(isElimated[index]==true) continue;FlowNetwork flowNet = formFlowNet(index);FordFulkerson maxflow = new FordFulkerson(flowNet, N + (N - 2) * (N - 1) /2, N + (N - 2) * (N - 1) /2 + 1);        for (int v = 0; v < N; v++) {        if(N == index) continue;            if (maxflow.inCut(v)){            isElimated[index] = true;            subsets[index].add(reverseInt.get(v));            }        }}}private FlowNetwork formFlowNet(int index){FlowNetwork flownet = new FlowNetwork(N + (N - 2) * (N - 1) /2 + 2);int i = N;for(int row =0;row < N && i != N + (N - 2) * (N - 1) /2; row++){if(row == index) continue;int col = row + 1;for(; col < N; col++){if(col == index) continue;flownet.addEdge(new FlowEdge(N + (N - 2) * (N - 1) / 2,i,g[row][col]));flownet.addEdge(new FlowEdge(i,row,Double.POSITIVE_INFINITY));flownet.addEdge(new FlowEdge(i,col,Double.POSITIVE_INFINITY));i++;}}for(int j =0;j<N;j++){if(j != index){flownet.addEdge(new FlowEdge(j,N + (N - 2) * (N - 1) /2 + 1,w[index] + r[index] - w[j] ));}}return flownet;}public int numberOfTeams(){// number of teamsreturn N;}public Iterable<String> teams(){// all teamsreturn teams.keys();}public int wins(String team){// number of wins for given teamif(w == null) throw new NullPointerException();if(!teams.contains(team)) throw new IllegalArgumentException();return w[teams.get(team)];}public int losses(String team){// number of losses for given teamif(l == null) throw new NullPointerException();if(!teams.contains(team)) throw new IllegalArgumentException();return l[teams.get(team)];}public int remaining(String team){// number of remaining games for given teamif(r == null) throw new NullPointerException();if(!teams.contains(team)) throw new IllegalArgumentException();return r[teams.get(team)];}public int against(String team1, String team2){// number of remaining games between team1 and team2if(g == null) throw new NullPointerException();if(!teams.contains(team1) || !teams.contains(team2)) throw new IllegalArgumentException();int i = teams.get(team1);int j = teams.get(team2);return g[i][j];}public boolean isEliminated(String team){// is given team eliminated?if(!teams.contains(team)) throw new IllegalArgumentException();if(isElimated == null) throw new NullPointerException();return isElimated[teams.get(team)];}public Iterable<String> certificateOfElimination(String team) {// subset R of teams that eliminates given team; null if not eliminatedif(!teams.contains(team)) throw new IllegalArgumentException();if(!isElimated[teams.get(team)]) return null;return subsets[teams.get(team)];}public static void main(String[] args) {    BaseballElimination division = new BaseballElimination(args[0]);    for (String team : division.teams()) {        if (division.isEliminated(team)) {            StdOut.print(team + " is eliminated by the subset R = { ");            for (String t : division.certificateOfElimination(team)) {                StdOut.print(t + " ");            }            StdOut.println("}");        }        else {            StdOut.println(team + " is not eliminated");        }    }}}


0 0
原创粉丝点击