Cod sursa(job #2710689)

Utilizator Andrei-27Arhire Andrei Andrei-27 Data 22 februarie 2021 21:19:35
Problema Flux maxim de cost minim Scor 40
Compilator java Status done
Runda Arhiva educationala Marime 5.74 kb
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());
        }
    }
}