Cod sursa(job #1045774)

Utilizator OwlreeRobert Badea Owlree Data 2 decembrie 2013 00:19:11
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.51 kb
//
// Infoarena - Cuplaj Maxim In Graf Bipartit
//
// http://www.infoarena.ro/problema/cuplaj
//
// Robert M. Badea
//
// I really need to set up a convention
// for these comments tho.
//

#include <iostream>
#include <vector>
#include <queue>
#include <fstream>

using namespace std;

const int MAX_LEVEL = 12500001;

class Graph
{
    private:
    vector<vector<int> >* adj;
    int sz;
    
    public:
    Graph(int vertices)
    {
        adj = new vector<vector<int> >(vertices + 1);
        sz = vertices;
    }
    
    void add_edge(int a, int b)
    {
        if (a == 0 || b == 0)
        {
            throw 201;
        }
        
        adj -> at(a).push_back(b);
        adj -> at(b).push_back(a);
    }
    
    vector<int>* adjacent_vertices(int v)
    {
        return &(adj -> at(v));
    }
    
    int size()
    {
        return sz;
    }
};

class Matching
{
    private:
    Graph* graph;
    vector<int>* matching;
    vector<int>* dist;
    int delimiter;
    int size;
    int matching_sz;
    
    // is there an augmented path in the graph?
    bool augmented_path()
    {
        queue<int> q;
        
        for (int i = 1; i < delimiter; ++i)
        {
            if (matching -> at(i) == 0)
            {
                dist -> at(i) = 0;
                q.push(i);
            }
            else
            {
                dist -> at(i) = MAX_LEVEL;
            }
            
        }
        
        (*dist)[0] = MAX_LEVEL;
        
        while (!q.empty())
        {
            int v = q.front();
            q.pop();
            
            if ((*dist)[v] < (*dist)[0])
            {
                vector<int>* adj = graph -> adjacent_vertices(v);
                int adj_nodes = (int)adj -> size();
                for (int i = 0; i < adj_nodes; ++i)
                {
                    int u = adj -> at(i);
                    if (dist -> at(matching -> at(u)) == MAX_LEVEL)
                    {
                        dist -> at(matching -> at(u)) = dist -> at(v) + 1;
                        q.push(matching -> at(u));
                    }
                }
            }
        }
        
        return dist -> at(0) != MAX_LEVEL;
    }
    
    // augment
    bool augment(int v)
    {
        if (v != 0)
        {
            vector<int>* adj = graph -> adjacent_vertices(v);
            int adj_n = (int)adj -> size();
            
            for (int i = 0; i < adj_n; ++i)
            {
                int u = adj -> at(i);
                
                if (dist -> at(matching -> at(u)) == true)
                {
                    (*matching)[u] = v;
                    (*matching)[v] = u;
                    return true;
                }
            }
            (*dist)[v] = MAX_LEVEL;
            return false;
        }
        else
        {
            return true;
        }
    }
    
    
    
    int find_matching()
    {
        int matching_n = 0;
        
        while (augmented_path())
        {
            for (int i = 1; i < delimiter; ++i)
            {
                if (matching -> at(i) == 0)
                {
                    if (augment(i))
                    {
                        matching_n ++;
                    }
                }
            }
        }
        
        return matching_n;
    }
    
    public:
    Matching(Graph* _graph, int _delimiter)
    {
        graph       = _graph;
        delimiter   = _delimiter;
        size        = graph -> size();
        matching    = new vector<int>(size);
        dist        = new vector<int>(size);
        
        for (int i = 0; i < size; ++i)
        {
            (*matching)[i] = 0;
        }
        
        matching_sz = find_matching();
    }
    
    int matching_size()
    {
        return matching_sz;
    }
    
    vector<int>* match()
    {
        return matching;
    }
};

int main()
{
    int N, M, P;
    
    ifstream fin("cuplaj.in");
    ofstream fout("cuplaj.out");
    
    fin >> N >> M >> P;
    cout << N << M << P;
    
    Graph* graph = new Graph(N + M + 1);
    
    for (int i = 0; i < P; ++i)
    {
        int x;
        int y;
        
        fin >> x;
        fin >> y;
        
        graph -> add_edge(x, y);
    }
    
    Matching* matching = new Matching(graph, N + 1);
    
    fout << matching -> matching_size() << "\n";
    
     vector<int>* match = matching -> match();
     
     for (int i = 1; i < N; ++i)
     {
         if (match -> at(i) == match -> at (match -> at(i)))
         {
             fout << i << " " << match -> at(i) << "\n";
         }
     }
    
    return 0;
}