Cod sursa(job #2552629)

Utilizator AndreiD31Dragan Andrei AndreiD31 Data 21 februarie 2020 01:19:59
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.84 kb
#include <bits/stdc++.h>
#define NMAX 20100
using namespace std;

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

vector <int> v[10100];
int viz[10100],M1[10100],M2[10100];

int cupleaza(int nod)
{
    if(viz[nod]==1) return 0; /// deja a fost luata in considerare
                              /// deci daca deja a fost luata in considerare si M1[nod] e inca 0 => ca nu am cum sa o cuplez in acest caz

    viz[nod]=1; /// o iau in considerare
    for(int i=0;i<v[nod].size();i++)
    {
        int vecin=v[nod][i];
        if(M2[vecin]==0) /// daca e liber, go for it, il pui si mergi mai departe, poate obtii vreo solutie buna (in cazul asta am gasit o bucata de pamant libera)
        {
            M2[vecin]=nod; /// ii atribui bucatii de pamant legiunea respectiva
            M1[nod]=vecin; /// dar si invers, ii atribui legiunii, bucata de pamant respectiva
            return 1;
        }
    }

    /// in for-ul asta ajung daca nu am gasit nicio bucata libera de pamant
    /// ce fac? iau o bucata existenta si incerc sa o eliberez fortat
    for(int i=0;i<v[nod].size();i++)
    {
        int vecin=v[nod][i];
        if(cupleaza(M2[vecin])) /// bucata de pamant vecin are deja o legiune. ma uit daca exista cumva vreo alta bucata de pamant libera pentru a cupla legiunea asta
                                /// adica pentru legiunea corespunzatoare bucatii de pamant vecin, intru inca o data in cupleaza si daca gasesc o alta bucata de pamant libera, in primul for o sa obtin return 1
        {
            /// daca am putut sa cuplez acea legiune cu alta bucata, atunci legiunea mea actuala o cuplez cu bucata asta
            M2[vecin]=nod;
            M1[nod]=vecin;
            return 1;
        }
    }

    /// daca pana acum nu am dat niciun return 1 => ca nu exsita niciun mod de a cupla legiunea nod :(
    return 0;
}

int n,m,e,OK,legiuni,i,x,y;
int main()
{
    f>>n>>m>>e;
    for(i=1;i<=e;i++)
    {
        f>>x>>y;
        v[x].push_back(y);
    }

    OK=1;
    while(OK) /// fac cat timp pot sa ii atribui pamant unei legiuni
    {
        OK=0;
        /// vine un general nou (sau vechi - adica vine iarasi) si refacem procedeul
        /// ideea e ca relatiile de cuplare se pastreaza (la venirea unui general nou, ele eventual se schimba)
        for(i=1;i<=n;i++)viz[i]=0; /// nu a fost luat in considerare de generalul actual
        for(i=1;i<=n;i++)
        {
            if(M1[i]==0) /// daca momentan nu i-am dat leginuii nicio bucata de pamant
            {
                int ok=cupleaza(i);
                if(ok==1) /// pot sa cuplez legiunea i
                {
                    OK=1;
                    legiuni++;
                }
            }
        }
    }

    g<<legiuni<<'\n';
    for(i=1;i<=n;i++)
        if(M1[i]!=0)g<<i<<" "<<M1[i]<<'\n';
    return 0;
}