Pagini recente » Cod sursa (job #2706121) | Cod sursa (job #3160839) | Cod sursa (job #2879820) | Cod sursa (job #2920055) | Cod sursa (job #3278036)
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();
}
}