Pagini recente » Cod sursa (job #2584270) | Cod sursa (job #2474288) | Cod sursa (job #3240242) | Cod sursa (job #3241804) | Cod sursa (job #2710689)
import java.util.*;
import java.io.*;
import java.lang.*;
public class Main {
private static int[] prio;
static class Vertex {
public int index_, val;
Vertex(int index_, int val) {
this.index_ = index_;
this.val = val;
}
}
static class Edge {
int neighbor, flow, capacity, cost, reverse_edge;
Edge(int neighbor, int capacity, int cost, int reverse_edge) {
this.neighbor = neighbor;
this.capacity = capacity;
this.cost = cost;
this.reverse_edge = reverse_edge;
}
}
public static Vector<Edge>[] createGraph(int n) {
Vector<Edge>[] graph = new Vector[n];
for (int i = 0; i < n; i++)
graph[i] = new Vector<>();
return graph;
}
public static void addEdge(Vector<Edge>[] graph, int s, int t, int cap, int cost) {
graph[s].add(new Edge(t, cap, cost, graph[t].size()));
graph[t].add(new Edge(s, 0, -cost, graph[s].size() - 1));
}
static void bellmanFord(Vector<Edge>[] graph, int s, int[] dist) {
int n = graph.length;
Arrays.fill(dist, Integer.MAX_VALUE);
dist[s] = 0;
boolean[] inqueue = new boolean[n];
ArrayDeque<Integer> Deque = new ArrayDeque<>();
Deque.add(s);
while (Deque.size() > 0) {
int u = Deque.poll();
inqueue[u] = false;
for (int i = 0; i < graph[u].size(); i++) {
Edge e = graph[u].get(i);
if (e.capacity <= e.flow )
continue;
int v = e.neighbor;
int ndist = dist[u] + e.cost;
if (dist[v] > ndist) {
dist[v] = ndist;
if (!inqueue[v]) {
inqueue[v] = true;
Deque.add(v);
}
}
}
}
}
static class VertexComparator implements Comparator<Vertex> {
public int compare(Vertex i, Vertex j) {
return Integer.compare(prio[i.index_], prio[j.index_]);
}
}
public static int[] minCostFlow(Vector<Edge>[] graph, int s, int t, int maxf) {
int n = graph.length;
prio = new int[n];
int[] curflow = new int[n];
int[] prevedge = new int[n];
int[] prevnode = new int[n];
int[] pot = new int[n];
bellmanFord(graph, s, pot);
int flow = 0;
int flowCost = 0;
while (flow < maxf) {
PriorityQueue<Vertex> q = new PriorityQueue<>(new VertexComparator());
q.add(new Vertex(s, 0));
Arrays.fill(prio, Integer.MAX_VALUE);
prio[s] = 0;
boolean[] used = new boolean[n];
curflow[s] = Integer.MAX_VALUE;
while (!used[t] && !q.isEmpty()) {
Vertex cur = q.remove();
int u = cur.index_;
used[u] = true;
for (int i = 0; i < graph[u].size(); i++) {
Edge e = graph[u].get(i);
if (e.flow >= e.capacity)
continue;
int v = e.neighbor;
int curr = prio[u] + e.cost + pot[u] - pot[v];
if (prio[v] > curr) {
prio[v] = curr;
q.add(new Vertex(v, curr));
prevnode[v] = u;
prevedge[v] = i;
curflow[v] = Math.min(curflow[u], e.capacity - e.flow);
}
}
}
if (prio[t] == Integer.MAX_VALUE)
break;
for (int i = 0; i < n; i++)
if (used[i])
pot[i] += prio[i] - prio[t];
int df = Math.min(curflow[t], maxf - flow);
flow += df;
for (int v = t; v != s; v = prevnode[v]) {
Edge e = graph[prevnode[v]].get(prevedge[v]);
e.flow += df;
graph[v].get(e.reverse_edge).flow -= df;
flowCost += df * e.cost;
}
}
return new int[]{flow, flowCost};
}
public static void main(String[] args) throws FileNotFoundException {
InputReader in = new InputReader(new FileInputStream("fmcm.in"));
PrintWriter out = new PrintWriter(new FileOutputStream("fmcm.out"));
int n = in.nextInt(), m = in.nextInt();
int source = in.nextInt() - 1, destination = in.nextInt() - 1;
Vector<Edge>[] graph = createGraph(n);
while (m-- > 0) {
int x = in.nextInt() - 1;
int y = in.nextInt() - 1;
int cost = in.nextInt();
int capacity = in.nextInt();
addEdge(graph, x, y, cost, capacity);
}
out.println(minCostFlow(graph, source, destination, Integer.MAX_VALUE)[1]);
out.close();
}
static class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
}
}