Cod sursa(job #2968698)

Utilizator ArseniuVictorStefanArseniu Victor Stefan ArseniuVictorStefan Data 21 ianuarie 2023 20:12:54
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.5 kb
#include <stdio.h>

// represents no node, no edge, no value etc.
#define NONE (-1)

// the maximum dimensions of the graph
#define NMAX (10'000)
#define MMAX (10'000)
#define EMAX (100'000)

// the graph
struct
{
    // the edges of the graph
    struct
    {
        int v; // the node this edge leads to
        int next; // the next edge
    } edges[EMAX];

    // the first edge of each node
    int begin[NMAX];

    // for each node in U, its pair in V
    int l[NMAX];

    // for each node in V, its pair in U
    int r[MMAX];

    // for each node in U, whether or not it was used in the current iteration
    bool used[NMAX];

    // the no. of nodes and no. of edges
    int n, m, e;
    
    // init the graph with _n nodes
    void init(int _n, int _m)
    {
        n = _n; m = _m;
        for(int u = 0; u < n; u++)
            begin[u] = NONE;
        
        // set the pairs
        for(int u = 0; u < n; u++)
            l[u] = NONE;
        for(int u = 0; u < m; u++)
            r[u] = NONE;
    }

    // adds an edge from u to v
    void add_edge(int u, int v)
    {
        edges[e] = { v, begin[u] };
        begin[u] = e++;
    }

    // DFS from u to find the augmenting paths and add them to the maximal matching
    bool dfs(int u)
    {
        // if u is used, return false
        if(used[u])
            return false;
        
        // mark u as used
        used[u] = true;
        
        // go through the neighbours of u
        for(int i = begin[u]; i != NONE; i = edges[i].next)
        {
            int v = edges[i].v;

            // if the neighbour isn't in use, link it to u
            if(r[v] == NONE)
            {
                l[u] = v;
                r[v] = u;
                return true;
            }
        }

        // if this is reached, then all neighbours of u are in use, so try to reroute
        for(int i = begin[u]; i != NONE; i = edges[i].next)
        {
            int v = edges[i].v;

            // if we can reroute, do it
            if(dfs(r[v]))
            {
                l[u] = v;
                r[v] = u;
                return true;
            }
        }

        // if this is reached, then u can't be connected
        return false;
    }
} graph;

int main()
{
    // open the files
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);

    // read the graph
    int n, m, e;
    scanf("%d %d %d", &n, &m, &e);

    // init the graph
    graph.init(n, m);

    // read the edges
    for(int i = 0; i < e; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        u--; v--;

        graph.add_edge(u, v);
    }

    // reroute until not possible anymore
    bool done;
    do
    {
        // reset done and used
        done = true;
        for(int u = 0; u < n; u++)
            graph.used[u] = false;
        
        // go through the free nodes in U and try to match them
        for(int u = 0; u < n; u++)
            if(graph.l[u] == NONE)
                done = (done && !graph.dfs(u));
    } while (!done);
    
    // count the cardinality
    int cardinality = 0;
    for(int u = 0; u < n; u++)
        if(graph.l[u] != NONE)
            cardinality++;
    
    // print the cardinality
    printf("%d\n", cardinality);

    // print the set
    for(int u = 0; u < n; u++)
        if(graph.l[u] != NONE)
            printf("%d %d\n", u + 1, graph.l[u] + 1);

    // exit
    return 0;
}