Pagini recente » Cod sursa (job #1771661) | Cod sursa (job #2383399) | Cod sursa (job #1761985) | Cod sursa (job #539189) | Cod sursa (job #1741390)
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
InputReader in = new InputReader(new FileInputStream("cuplaj.in"));
int N = in.nextInt();
int M = in.nextInt();
int P = in.nextInt();
MaximumMatching MM = new MaximumMatching(N, M);
for (int i = 0; i < P; i++) {
int a = in.nextInt();
int b = in.nextInt();
MM.addEdge(a, b);
}
PrintWriter out = new PrintWriter(new FileOutputStream("cuplaj.out"));
out.println(MM.maximumMatching());
int[] matching = MM.getMatched();
for (int i = 0; i < N; i++) {
int v = matching[i];
if (v != -1)
out.println((i + 1) + " " + v);
}
out.close();
}
static class InputReader{
private BufferedReader reader;
private StringTokenizer tokenizer;
InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 1 << 20);
tokenizer = null;
}
private String nextToken() {
while (tokenizer == null || !tokenizer.hasMoreTokens()){
try {
tokenizer = new StringTokenizer(reader.readLine());
}
catch (IOException e){
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
int nextInt() {
return Integer.parseInt(nextToken());
}
String nextString(){
return nextToken();
}
}
static class Graph{
private static class Edge{
int node;
int next;
Edge(int node, int next){
this.node = node;
this.next = next;
}
}
public final static int NIL = -1;
private int[] head;
private ArrayList<Edge> graph;
private int N;
private int contor;
public int getN() {
return N;
}
void initialize(final int N){
head = new int[N];
graph = new ArrayList<>();
System.gc();
this.N = N;
this.contor = 0;
for (int i = 0; i < N; ++i)
head[i] = NIL;
}
void addEdge(int x, int y){
x--; y--;
graph.add(new Edge(y, head[x]));
head[x] = contor++;
}
int getHead(int node){
node--;
return head[node];
}
int getNext(int p){
assert 0 <= p && p < contor;
return graph.get(p).next;
}
int getNeighbour(int p){
assert 0 <= p && p < contor;
return graph.get(p).node + 1;
}
}
static class MaximumMatching {
private Graph graph;
private int V1, V2;
private boolean[] used;
private int[] matched;
MaximumMatching(int V1, int V2){
graph = new Graph();
graph.initialize(V1);
this.V1 = V1;
this.V2 = V2;
used = new boolean[V1];
matched = new int[V1 + V2];
}
void addEdge(int from, int to){
graph.addEdge(from, V1 + to);
}
private boolean pairUp(int node){
assert 0 <= node && node < V1;
if (used[node])
return false;
used[node] = true;
for (int p = graph.getHead(node + 1); p != graph.NIL; p = graph.getNext(p)) {
int son = graph.getNeighbour(p) - 1;
if (matched[son] == -1){
matched[son] = node;
matched[node] = son;
return true;
}
}
for (int p = graph.getHead(node + 1); p != graph.NIL; p = graph.getNext(p)) {
int son = graph.getNeighbour(p) - 1;
if (pairUp(matched[son])){
matched[son] = node;
matched[node] = son;
return true;
}
}
return false;
}
int maximumMatching(){
Arrays.fill(matched, -1);
boolean changed;
do {
changed = false;
Arrays.fill(used, false);
for (int i = 0; i < V1; i++)
if (matched[i] == -1)
changed |= pairUp(i);
} while (changed);
int matching = 0;
for (int i = 0; i < V1; i++)
if (matched[i] != -1)
matching++;
return matching;
}
int[] getMatched(){
int[] matching = Arrays.copyOf(matched, V1);
for (int i = 0; i < matching.length; i++) {
if (matching[i] != -1)
matching[i] = matching[i] - V1 + 1;
}
return matching;
}
}
}