Cod sursa(job #3278036)

Utilizator pifaDumitru Andrei Denis pifa Data 18 februarie 2025 16:51:25
Problema Cuplaj maxim in graf bipartit Scor 30
Compilator java Status done
Runda Arhiva educationala Marime 4.25 kb
import java.util.*;
import java.io.*;

public class Main {

    static class Pair {
        int node;
        int flow;
        public Pair(int node, int flow) {
            this.node = node;
            this.flow = flow;
        }
    }

    static class Edge {
        int from, to;
        public Edge(int from, int to) {
            this.from = from;
            this.to = to;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Edge edge = (Edge) o;
            return from == edge.from && to == edge.to;
        }

        @Override
        public int hashCode() {
            return Objects.hash(from, to);
        }
    }

    static List<List<Integer>> adj;
    static int n, m, k;
    static Map<Edge, Integer> cap;

    public static int bfs(int source, int sink, int[] parent) {
        Arrays.fill(parent, -1);
        parent[source] = -2;
        Queue<Pair> q = new LinkedList<>();
        q.add(new Pair(source, Integer.MAX_VALUE));
        while (!q.isEmpty()) {
            Pair cur = q.poll();
            int node = cur.node;
            int flow = cur.flow;
            for (int next : adj.get(node)) {
                Edge e = new Edge(node, next);
                if (parent[next] == -1 && cap.getOrDefault(e, 0) > 0) {
                    parent[next] = node;
                    int newFlow = Math.min(flow, cap.get(e));
                    if (next == sink) {
                        return newFlow;
                    }
                    q.add(new Pair(next, newFlow));
                }
            }
        }
        return 0;
    }

    public static int maxFlow(int source, int sink) {
        int flow = 0;
        int[] parent = new int[n + m + 2];
        int newFlow;
        while ((newFlow = bfs(source, sink, parent)) > 0) {
            flow += newFlow;
            int cur = sink;
            while (cur != source) {
                int prev = parent[cur];
                Edge forward = new Edge(prev, cur);
                Edge backward = new Edge(cur, prev);
                cap.put(forward, cap.get(forward) - newFlow);
                cap.put(backward, cap.getOrDefault(backward, 0) + newFlow);
                cur = prev;
            }
        }
        return flow;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("cuplaj.in"));
        PrintWriter pw = new PrintWriter(new FileWriter("cuplaj.out"));
        StringTokenizer x = new StringTokenizer(br.readLine());
        n = Integer.parseInt(x.nextToken());
        m = Integer.parseInt(x.nextToken());
        k = Integer.parseInt(x.nextToken());
        int source = 0, sink = n + m + 1;
        cap = new HashMap<>();
        adj = new ArrayList<>();
        for (int i = 0; i <= sink; i++) {
            adj.add(new ArrayList<>());
        }
        List<Edge> hold = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            Edge e = new Edge(source, i);
            cap.put(e, 1);
            adj.get(source).add(i);
            adj.get(i).add(source);
        }
        for (int i = 1; i <= m; i++) {
            Edge e = new Edge(n + i, sink);
            cap.put(e, 1);
            adj.get(n + i).add(sink);
            adj.get(sink).add(n + i);
        }
        for (int i = 0; i < k; i++) {
            x = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(x.nextToken());
            int b = Integer.parseInt(x.nextToken());
            b += n;
            Edge e = new Edge(a, b);
            adj.get(a).add(b);
            adj.get(b).add(a);
            cap.put(e, 1);
            hold.add(e);
        }
        br.close();
        int maxMatching = maxFlow(source, sink);
        Set<Edge> cuplaj = new HashSet<>();
        for (Edge edge : hold) {
            if (cap.getOrDefault(edge, 0) == 0) {
                cuplaj.add(new Edge(edge.from, edge.to - n));
            }
        }
        pw.println(cuplaj.size());
        for (Edge e : cuplaj) {
            pw.println(e.from + " " + e.to);
        }
        pw.flush();
    }
}