做業地址:http://coursera.cs.princeton.edu/algs4/assignments/baseball.htmlhtml
做業難點:算法
一、如何計算非平凡淘汰(Nontrivial elimination)?網絡
關鍵在於理解題目的這句話「If all edges in the maxflow that are pointing from s are full, then this corresponds to assigning winners to all of the remaining games in such a way that no team wins more games than x. If some edges pointing from s are not full, then there is no scenario in which team x can win the division.」數據結構
1)平凡淘汰:從全部隊伍中直接淘汰w[i] + r[i] < max{w[i]}的隊伍;ide
2)非平凡淘汰的算法中心思想:若是一支隊伍完成的勝場不能被其餘隊伍超越,則這支隊伍不會被淘汰。極端狀況下,第i支隊伍完成w[i] + r[i]勝場時,剩下的隊伍輸掉全部與平凡淘汰的隊伍的對局其勝場最少。以其中一支未被平凡淘汰的隊伍的w[i] + r[i]做爲全部隊伍須要完成的勝場次,其餘隊伍須要完成w[i] + r[i] - w[j]個勝場可與第i支隊伍戰平,即[team vertices] -> [sink vertice]的capacity爲:w[i] + r[i] - w[j];ui
3)根據剩餘隊伍之間的game[][]構建[source vertice] -> [game vertices]邊;this
4)而後按題目提示構建FlowNetWork:spa
from | to | capacity |
[source vertice] | [game vertices] | game[i][j] |
[game vertices] | [team vertices] | infinity |
[team vertices] | [sink vertice] | w[i] + r[i] - w[j] |
5)經過FordFulkerson算法求解每支隊伍source端的流量,肯定[source vertice] -> [game vertices]是否達到最大流量,若是沒有達到最大流量,說明FlowNetWork中的比賽沒有進行完某支隊伍的勝場已達到w[i]+r[i],亦即存在最終獲勝的隊伍勝場大於w[i]+r[i],說明這第i支隊伍須要被淘汰;code
6)重複2)-5)步,直到遍歷求解完全部未被平凡淘汰的隊伍。htm
二、如何計算隊伍是被哪些隊伍淘汰的?
1)平凡淘汰:隊伍是被目前領先的隊伍直接淘汰;
2)非平凡淘汰:根據最大流最小切定理(以及題目提示:What the min cut tells us.),隊伍被過source的最小切上的頂點所淘汰。
容易扣分點:
本題目的特徵是要麼沒有理解題意難以求解,要麼很順利得出最終結果。
部分代碼:
一、數據結構:
private int[] w, l, r; private int[][] games; private Map<String, Integer> teamMap; private int maxWins = -1; private String leadingTeam; private static final double MAX_EDGE = Double.POSITIVE_INFINITY; private class spGraph { FordFulkerson ff; FlowNetwork flowNetwork; int s; public spGraph(FordFulkerson ff, FlowNetwork network, int source, int sink) { super(); this.ff = ff; this.flowNetwork = network; this.s = source; } }
二、構造網絡流圖:
private spGraph buildGraph(int id) { int n = numberOfTeams(); int source = n; int sink = n + 1; int gameVertice = n + 2; int curMaxWins = w[id] + r[id]; Set<FlowEdge> edges = new HashSet<FlowEdge>(); for (int i = 0; i < n; i++) { if (i == id || trvialEnd(i)) continue; for (int j = 0; j < i; j++) { if (j == id || trvialEnd(j) || games[i][j] == 0) continue; edges.add(new FlowEdge(source, gameVertice, games[i][j])); edges.add(new FlowEdge(gameVertice, i, MAX_EDGE)); edges.add(new FlowEdge(gameVertice, j, MAX_EDGE)); gameVertice++; } edges.add(new FlowEdge(i, sink, curMaxWins - w[i])); } FlowNetwork flowNetwork = new FlowNetwork(gameVertice); for (FlowEdge edge : edges) flowNetwork.addEdge(edge); FordFulkerson ff = new FordFulkerson(flowNetwork, source, sink); return new spGraph(ff, flowNetwork, source, sink); }