Poj_1273 Drainage Ditches
初学图论的最大流问题,讲讲自己的学后的想法:
做这种题目的大概的套路就是:找一条从起点到终点的路线,(取该路线上权值最小的边,为该次查找的最小的流)然后反转该路线的流向,重复多次直至找不到为止,将每次找到的最小流加起来,就是起点到终点的最大流,也就是问题的解。
(多组输入注意初始化哦(*^__^*) )
package netflow;
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.LinkedList;
import java.util.Queue;
public class Poj_1273 {
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static String next() throws IOException {
in.nextToken();
return (String) in.sval;
}
static int map[][] = new int[205][205]; // 二维数组存放图
static int path[] = new int[205], flow[] = new int[205]; // 前驱结点 , 当前路线上的最小流量(过该点)
static int start, end; // 起点、终点
static int n, m, u, v, cost;
static Queue<Integer> q = new LinkedList<Integer>();
public static void main(String[] args) throws IOException {
while (in.nextToken() != StreamTokenizer.TT_EOF) {
n = (int) in.nval;
m = nextInt();
Init(); // 多组输入一定要注意初始化啦、
for (int i = 0; i < n; i++) {
u = nextInt();
v = nextInt();
cost = nextInt();
map[u][v] += cost; // 可能一条边输入多次、
}
start = 1;
end = m;
out.println(Edmonds_karp());
out.flush();
}
}
public static void Init() {
for (int i = 0; i < 205; i++) {
for (int j = 0; j < 205; j++) {
map[i][j] = 0;
}
}
}
public static int bfs() {
q.clear();
for (int i = 0; i < 205; i++) {
path[i] = -1;
}
path[start] = 0; // 开始的前驱结点为0,
flow[start] = Integer.MAX_VALUE;
q.add(start);
while (!q.isEmpty()) {
int t = q.poll();
if (t == end) {
break;
}
for (int i = 1; i <= m; i++) {
if (i != start && path[i] == -1 && map[t][i] != 0) { // 表示可以往下面走、
flow[i] = Math.min(flow[t] , map[t][i]); // 水流的流向 t -> i (t之前存的最小的,和当前的流量比,取较小的)
q.add(i);
path[i] = t;
}
}
}
if (path[end] == -1) {
return -1;
}
return flow[end]; // 返回当前路线的最大流量(支流)
}
public static int Edmonds_karp() {
int max_flow = 0, step, now = 0, pre = 0;
while ((step = bfs()) != -1) { // 找到了一个从起点到终点的路线,(支流的最大流量)
max_flow += step;
now = end;
while (now != start) {
pre = path[now]; // 回退, 对该路线的水流量反转、
map[pre][now] -= step;
map[now][pre] += step;
now = pre;
}
}
return max_flow; // 返回起点到终点的最大流量、
}
}