private void solve(Team t) { if (eliminators.containsKey(t.name)) { return; } // result is cached, so don't recalculate it // Trivial elimination if (!t.equals(teams[leader]) && isTriviallyEliminated(t)) { eliminators.put( t.name, new SET<String>() { { add(teams[leader].name); } }); // I bet checkstyle HATES this. //TODO: I bet this is a bug where sliminators are // overwritten return; } // Maxflowy realzo elimination FordFulkerson ffFlow = graphTheTeam(t); if (isNumericallyEliminated(t, ffFlow.value())) { for (int i = 0; i < numberOfTeams(); i++) { if (ffFlow.inCut(i)) { SET<String> winners = new SET<String>(); if (eliminators.containsKey(t.name)) { winners = eliminators.get(t.name); } winners.add(teams[i].name); eliminators.put(t.name, winners); } } } }
/** @return is given team eliminated? */ public boolean isEliminated(String team) { checkArgument(team); int teamIndex = team2Index.get(team); int maxPossibleWinCount = remainingCounts[teamIndex] + winCounts[teamIndex]; if (maxPossibleWinCount < maxWinCountCurrent) { return true; } int nodeCount = 2 // s, t + teamCount * (teamCount - 1) / 2 // game vertices + teamCount; // team vertices // 0..N-1 for team vertices // N..N*(N+1)/2 for game vertices // last 2 node for s and t FlowNetwork network = new FlowNetwork(nodeCount); int s = nodeCount - 2; int t = nodeCount - 1; double sCapacity = 0; // edge from team vertices to t for (int i = 0; i < teamCount; i++) { if (i != teamIndex) { double weight = maxPossibleWinCount - winCounts[i]; FlowEdge edge = new FlowEdge(i, t, weight); network.addEdge(edge); } } int gameNodeIndex = teamCount - 1; for (int i = 0; i < teamCount; i++) { for (int j = i + 1; j < teamCount; j++) { gameNodeIndex++; if (i == teamIndex || j == teamIndex) { continue; } // edge from s to game vertices double weight = remainGames[i][j]; FlowEdge edge = new FlowEdge(s, gameNodeIndex, weight); network.addEdge(edge); sCapacity += weight; // edges from game vertices to team vertices edge = new FlowEdge(gameNodeIndex, i, Double.POSITIVE_INFINITY); network.addEdge(edge); edge = new FlowEdge(gameNodeIndex, j, Double.POSITIVE_INFINITY); network.addEdge(edge); } } FordFulkerson alg = new FordFulkerson(network, s, t); if (Math.abs(alg.value() - sCapacity) < 1E-6) { return false; } return true; }
public BaseballElimination(String filename) { In in = new In(filename); V = in.readInt(); teamID = new ST<String, Integer>(); teamName = new ST<Integer, String>(); teamInfo = new int[V][V + 3]; subset = (Bag<Integer>[]) new Bag[V]; elimin = new Boolean[V]; for (int i = 0; i < V; i++) { subset[i] = new Bag<Integer>(); } for (int i = 0; i < V; i++) { String name = in.readString(); teamID.put(name, i); teamName.put(i, name); for (int j = 0; j < V + 3; j++) { teamInfo[i][j] = in.readInt(); } } int offset = 1 + V * (V - 1) / 2; for (int x = 0; x < V; x++) { if (trivalElimination(x)) { // StdOut.println("team " + teamName.get(x) + "is trivally eliminated"); elimin[x] = true; continue; } FlowNetwork G = new FlowNetwork(offset + V + 1); int s = 0; int t = offset + V; int point = 1; int remainGameNumber = 0; for (int i = 0; i < V; i++) { for (int j = i + 1; j < V; j++) { if (i == x || j == x) { point++; continue; } if (teamInfo[i][j + 3] > 0) { FlowEdge edge = new FlowEdge(s, point, teamInfo[i][j + 3]); remainGameNumber += teamInfo[i][j + 3]; G.addEdge(edge); FlowEdge edge1 = new FlowEdge(point, offset + i, Double.POSITIVE_INFINITY); FlowEdge edge2 = new FlowEdge(point, offset + j, Double.POSITIVE_INFINITY); G.addEdge(edge1); G.addEdge(edge2); } point++; } } for (int i = 0; i < V; i++) { if (i == x) continue; int capacity = teamInfo[x][0] + teamInfo[x][2] - teamInfo[i][0]; FlowEdge edge = new FlowEdge(offset + i, t, capacity); G.addEdge(edge); } FordFulkerson maxflow = new FordFulkerson(G, s, t); if (maxflow.value() == remainGameNumber) { elimin[x] = false; } else { elimin[x] = true; if (debug == true) { StdOut.println("FlowNetWork" + G.toString()); } for (int i = 0; i < V; i++) { if (i == x) continue; if (maxflow.inCut(offset + i)) { subset[x].add(i); } } } } }