try { scanner = new Scanner(file); this.V = scanner.nextInt(); if (V < 0) { thrownew IllegalArgumentException("V can't be negative"); } adj = new HashMap[V]; for (int i = 0; i < V; i++) { adj[i] = new HashMap<>(); }
this.E = scanner.nextInt(); if (E < 0) { thrownew IllegalArgumentException("E can't be negative"); }
for (int i = 0; i < E; i++) { int v = scanner.nextInt(); int w = scanner.nextInt(); int weight = scanner.nextInt();
if (v == w) { thrownew IllegalArgumentException("存在自环边"); } if (adj[v].containsKey(w)) { thrownew IllegalArgumentException("存在平行边"); } // 表示有向 adj[v].put(w, weight); } } catch (Exception e) { e.printStackTrace(); }finally { scanner.close(); } }
// 另一构造方法 publicDirectedWeightedGraph(int V){ this.V = V; this.E = 0; this.adj = new HashMap[V]; for (int v = 0; v < V; v++) { adj[v] = new HashMap<>(); } }
publicintV(){ returnthis.V; }
publicintE(){ returnthis.E; }
publicintgetWeight(int v, int w){ validateVertex(v); validateVertex(w); if (!hasEdge(v, w)) { thrownew IllegalArgumentException(String.format("%d-%d 不存在", v, w)); } return adj[v].get(w); }
publicvoidsetWeight(int v, int w, int weight){ validateVertex(v); validateVertex(w); if (!hasEdge(v, w)) { thrownew IllegalArgumentException(String.format("%d-%d 不存在", v, w)); } adj[v].put(w, weight); }
publicvoidaddEdge(int v, int w, int weight){ validateVertex(v); validateVertex(w); if (v == w) { thrownew IllegalArgumentException("存在自环边"); } if (adj[v].containsKey(w)) { thrownew IllegalArgumentException("存在平行边"); }
adj[v].put(w, weight); E++; }
publicbooleanhasEdge(int v, int w){ validateVertex(v); validateVertex(w); return adj[v].containsKey(w); }
public Iterable<Integer> adj(int v){ validateVertex(v); return adj[v].keySet(); }
publicvoidvalidateVertex(int v){ if (v < 0 && v >= V) { thrownew IllegalArgumentException("节点超过 [0, V) 的范围"); } }
@Override public String toString(){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(String.format("V: %d, E: %d\n", this.V, this.E)); for (int v = 0; v < this.V; v++) { stringBuilder.append(String.format("%d : ", v)); for (Map.Entry w: adj[v].entrySet()) { stringBuilder.append(String.format("(%d: %d) ", w.getKey(), w.getValue())); } stringBuilder.append("\n"); } return stringBuilder.toString(); } }
当时媒体争议的是最后一个队,即 Detroit 队还有没有获胜的希望。从数据上看,如果 Detroit 剩下的 27 场全赢,那么它的赢的总场次是 $49 + 27 = 76$,比最强的 New York 还多一场,所以它还有赢的机会,但是这样想的话就忽略了一个事实,即使 Detroit 与其他四队的比赛都打赢了,但是这四个队之间还有比赛,也就说说这四个队它们的总胜场是会增加的。
所以现在又变为了这么一个问题,如果前四个队之间比赛,如果最终它们的胜场最多是 76 的话,说明 Detroit 队还有赢的希望,否则 Detroit 队没有赢的可能。现在我们如下建模
这个图分为三部分,第一部分
其中权值表示比赛场次,比如 s → NY-Bal 这条边的权值为 $5$,表示 NY 与 Bal 之间有五场比赛要打,可见这四个队伍总共要打 $5 + 8 + 7 + 2 + 7 = 27$ 场比赛。第二部分
这次的权值表示的是胜场的分配。第三部分
这时其中的权值表示每个队最多赢多少次,例如 NY 队目前 $75$ 分,它最多只能赢一场。如果上述网络流的最大流大于等于比赛的总场次,所以存在一种方案能够分配所有胜场使得所有队的得分最多只有 $76$ 分。