Cod sursa(job #1396016)

Utilizator rootsroots1 roots Data 21 martie 2015 22:29:26
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.81 kb
#include <fstream>
#include <vector>
#include <queue>

#define MAXV 10001

using namespace std;

ifstream in("cuplaj.in");
ofstream out("cuplaj.out");

int L, R, E;
vector <int> G[2 * MAXV];
int match[2 * MAXV];
int father[2 * MAXV];
int dist[2 * MAXV];
vector <int> path;
int maxMatch = 0;
int root[2 * MAXV];

inline void readAndBuild() {
    in >> L >> R >> E;
    
    int x, y;
    for (int e = 0; e < E; ++ e) {
        in >> x >> y;
        
        G[x].push_back(y + L);
        G[y + L].push_back(x);
    }
}

inline bool bfs() {
    bool foundPath = false;
    
    queue <int> q;
    for (int node = L; node > 0; -- node) {
        if (match[node] == 0) {
            father[node] = node;
            dist[node] = 0;
            root[node] = node;
            q.push(node);
        } else {
            father[node] = -1;
            dist[node] = -1;
            root[node] = -1;
        }
    }
    for (int node = L + R; node > L; -- node) {
        if (match[node] == 0) {
            father[node] = 0;
            dist[node] = 0;
        } else {
            father[node] = -1;
            dist[node] = -1;
        }
    }
    
    for (int node; !q.empty(); q.pop()) {
        node = q.front();
        
        for (vector <int>::iterator it = G[node].begin(); it != G[node].end(); ++ it) {
            if ((match[*it] == node) == dist[node] % 2) {
                if (father[*it] == -1) {
                    father[*it] = node;
                    dist[*it] = dist[node] + 1;
                    root[*it] = root[node];
                    q.push(*it);
                } else if (father[*it] == 0) {
                    father[*it] = node;
                    dist[*it] = dist[node] + 1;
                    root[*it] = root[node];
                    
                    foundPath = true;
                    
                    path.push_back(*it);
                }
            }
        }
    }
    
    return foundPath;
}

inline void bipartiteMatchingWithHopcroftKarp() {
    for (bool existsAugmentingPath = bfs(); existsAugmentingPath; existsAugmentingPath = bfs()) {
        for (vector <int>::iterator it = path.begin(); it != path.end(); ++ it) {
            if (match[root[*it]]) continue;
            
            for (int node = *it; node != father[node]; node = father[node]) {
                if (dist[node] % 2 == 1) {
                    match[node] = father[node];
                    match[father[node]] = node;
                }
            }
            
            maxMatch ++;
        }
        
        path.clear();
    }
}

inline void printResult() {
    out << maxMatch << '\n';
    for (int i = 1; i <= L; ++ i) {
        if (match[i]) {
            out << i << ' ' << match[i] - L << '\n';
        }
    }
}

int main() {
    readAndBuild();
    bipartiteMatchingWithHopcroftKarp();
    printResult();
    
    return 0;
}