Cod sursa(job #1051460)

Utilizator OwlreeRobert Badea Owlree Data 10 decembrie 2013 03:25:33
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.53 kb
#include <fstream>

#include <vector>
#include <string>
#include <sstream>

using namespace std;

class Digraph
{
private:
    const int V;
    int E;
    vector< vector <int> >* adj;
    
public:
    
    // CONSTRUCTORS
    Digraph(int _V) : V(_V)
    {
        if (V < 0) throw 101; // number of vertices must be nonnegative
        E = 0;
        adj = new vector< vector<int> >(V);
        for (int v = 0; v < V; ++v)
        {
            (*adj)[v] = vector<int>();
        }
    }
    
    Digraph(Digraph* _G) : V(_G -> vertices())
    {
        // TO- DO: deep copy
    }
    
    // SET'S, MOD'S, etc
    void add_edge(int v1, int v2)
    {
        // should also check for duplicate edges
        // but there's not need for that
        
        E ++;
        (*adj)[v1].push_back(v2);
    }
    
    // GET'S
    int vertices()
    {
        return V;
    }
    
    int edges()
    {
        return E;
    }
    
    vector<int>* adjacent(int _v)
    {
        if (_v < 0 || _v >= V) throw 101;
        return &((*adj)[_v]);
    }
    
    // DEBUG
    string toString()
    {
        stringstream ss;
        ss << V << " vertices, " << E << " edges\n";
        for (int v = 0; v < V; ++v)
        {
            ss << v << ": ";
            int adj_v = (int)(*adj)[v].size();
            for (int i = 0; i < adj_v; ++i)
            {
                ss << (*adj)[v][i] << " ";
            }
            ss << "\n";
        }
        return ss.str();
    }
    
};

class MaximumMatching
{
private:
    Digraph* graph;
    vector<int>* left_to_right;
    vector<int>* right_to_left;
    vector<bool>* used;
    int sz;
    
    bool pairup(int v)
    {
        if ((*used)[v])
        {
            return false;
        }
        
        (*used)[v] = true;
        vector<int>* adj_v = graph -> adjacent(v);
        int adj_v_size = (int)adj_v -> size();
        
        for (int i = 0; i < adj_v_size; ++i)
        {
            int u = (*adj_v)[i];
            
            if (right_to_left -> at(u) == 0)
            {
                (*left_to_right)[v] = u;
                (*right_to_left)[u] = v;
                
                return true;
            }
        }
        
        for (int i = 0; i < adj_v_size; ++i)
        {
            int u = (*adj_v)[i];
            
            if (pairup(right_to_left -> at(u)))
            {
                (*left_to_right)[v] = u;
                (*right_to_left)[u] = v;
                
                return true;
            }
        }
        
        return false;
    }
    
    void make_matching()
    {
        bool there_is_something_to_do = true;
        
        while (there_is_something_to_do)
        {
            there_is_something_to_do = false;
            
            for (int i = 0; i < used -> size(); ++i)
            {
                (*used)[i] = false;
            }
            
            for (int i = 1; i < graph -> vertices(); ++i)
            {
                if (left_to_right -> at(i) == 0)
                {
                    there_is_something_to_do = pairup(i) || there_is_something_to_do;
                }
            }
        }
    }
    
    void make_size()
    {
        sz = 0;
        for (int i = 0; i < left_to_right -> size(); ++i)
        {
            sz += left_to_right -> at(i) != 0;
        }
    }
public:
    MaximumMatching(Digraph* _graph, int left_vertices_n, int right_vertices_n)
    {
        graph = _graph;
        used = new vector<bool>(graph -> vertices() + 10);
        left_to_right = new vector<int>(left_vertices_n + 10);
        right_to_left = new vector<int>(right_vertices_n + 10);
        
        make_matching();
        make_size();
    }
    
    vector<int>* left()
    {
        return left_to_right;
    }
    
    vector<int>* right()
    {
        return right_to_left;
    }
    
    int size()
    {
        return sz;
    }
    
};

int main(int argc, const char * argv[])
{
    ifstream fin("cuplaj.in");
    ofstream fout("cuplaj.out");
    
    int N, M, E;
    
    fin >> N >> M >> E;
    Digraph* graph = new Digraph(N + 1);
    
    for (int i = 0; i < E; ++i)
    {
        int a, b;
        fin >> a >> b;
        graph -> add_edge(a, b);
    }
    
    MaximumMatching* matching = new MaximumMatching(graph, N, M);
    
    vector<int>* left = matching -> left();
    int size = matching -> size();
    
    fout << size << "\n";
    for (int i = 0; i < left -> size(); ++i)
    {
        if (left -> at(i) != 0)
        {
            fout << i << " " << left -> at(i) << "\n";
        }
    }
    
    fin.close();
    fout.close();
    
    return 0;
}