You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 本题测试链接:
// https://lightoj.com/problem/internet-bandwidth
// 这是一道DinicAlgorithm算法的题
// 把如下代码粘贴进网页所提供的java编译器环境中
// 不需要修改任何内容可以直接通过
// 请看网页上的题目描述并结合main函数的写法去了解这个模板的用法
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
package class47;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Code03_DinicAlgorithm {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
int cases = (int) in.nval;
for (int i = 1; i <= cases; i++) {
in.nextToken();
int n = (int) in.nval;
in.nextToken();
int s = (int) in.nval;
in.nextToken();
int t = (int) in.nval;
in.nextToken();
int m = (int) in.nval;
Dinic dinic = new Dinic(n);
for (int j = 0; j < m; j++) {
in.nextToken();
int from = (int) in.nval;
in.nextToken();
int to = (int) in.nval;
in.nextToken();
int weight = (int) in.nval;
dinic.addEdge(from, to, weight);
dinic.addEdge(to, from, weight);
}
int ans = dinic.maxFlow(s, t);
out.println("Case " + i + ": " + ans);
out.flush();
}
}
}
public static class Edge {
public int from;
public int to;
public int available;
public Edge(int a, int b, int c) {
from = a;
to = b;
available = c;
}
}
public static class Dinic {
private int N;
private ArrayList<ArrayList<Integer>> nexts;
private ArrayList<Edge> edges;
private int[] depth;
private int[] cur;
public Dinic(int nums) {
N = nums + 1;
nexts = new ArrayList<>();
for (int i = 0; i <= N; i++) {
nexts.add(new ArrayList<>());
}
edges = new ArrayList<>();
depth = new int[N];
cur = new int[N];
}
public void addEdge(int u, int v, int r) {
int m = edges.size();
edges.add(new Edge(u, v, r));
nexts.get(u).add(m);
edges.add(new Edge(v, u, 0));
nexts.get(v).add(m + 1);
}
public int maxFlow(int s, int t) {
int flow = 0;
while (bfs(s, t)) {
Arrays.fill(cur, 0);
flow += dfs(s, t, Integer.MAX_VALUE);
Arrays.fill(depth, 0);
}
return flow;
}
private boolean bfs(int s, int t) {
LinkedList<Integer> queue = new LinkedList<>();
queue.addFirst(s);
boolean[] visited = new boolean[N];
visited[s] = true;
while (!queue.isEmpty()) {
int u = queue.pollLast();
for (int i = 0; i < nexts.get(u).size(); i++) {
Edge e = edges.get(nexts.get(u).get(i));
int v = e.to;
if (!visited[v] && e.available > 0) {
visited[v] = true;
depth[v] = depth[u] + 1;
if (v == t) {
break;
}
queue.addFirst(v);
}
}
}
return visited[t];
}
// 当前来到了s点s可变
// 最终目标是tt固定参数
// r收到的任务
// 收集到的流作为结果返回ans <= r
private int dfs(int s, int t, int r) {
if (s == t || r == 0) {
return r;
}
int f = 0;
int flow = 0;
// s点从哪条边开始试 -> cur[s]
for (; cur[s] < nexts.get(s).size(); cur[s]++) {
int ei = nexts.get(s).get(cur[s]);
Edge e = edges.get(ei);
Edge o = edges.get(ei ^ 1);
if (depth[e.to] == depth[s] + 1 && (f = dfs(e.to, t, Math.min(e.available, r))) != 0) {
e.available -= f;
o.available += f;
flow += f;
r -= f;
if (r <= 0) {
break;
}
}
}
return flow;
}
}
}