Cod sursa(job #1539805)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 1 decembrie 2015 17:11:10
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 4.12 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<bitset>

#define pb push_back
#define Nmax 20050
#define sursa 20005
#define dest 20006
#define INF 11

// algoritmul de rezolvare folosind algoritmul edmonds-karp

using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
int N,N1,N2,M;
bitset<Nmax> verif;

struct arc {
    int d=-1,cap,flow;
    arc *invers;
};

// arc.d=destinatia arcului
// arc.cap=capacitatea arcului
// arc.flow=fluxul arcului la un moment dat
// arc.invers=adresa arcului invers corespunzator arcului

#define arcp arc*
vector<arcp> v[Nmax];
arcp muchie_from_dad[Nmax];

// verif[i]=1 daca nodul i a fost verificat la parcurgerea bfs curenta
// v[i]=lista a arcelor adiacente la nodul i
// muchie_from_dad[i]=muchia de la tatal nodului i la nodul i pentru parcurgerea bfs curenta

bool bfs();

int main()
{
    f>>N1>>N2>>M;
    for (int i=1;i<=M;++i) { // se formeaza arcele de corespondenta intre cele 2 grafuri
        int x,y;
        f>>x>>y;
        arc *da1=new arc;
        arc *da2=new arc;
        da1->d=N1+y;
        da1->cap=1;
        da1->flow=0;
        v[x].pb(da1);

        da2->d=x;
        da2->cap=da2->flow=0;
        v[N1+y].pb(da2);

        v[x][v[x].size()-1]->invers=v[N1+y][v[N1+y].size()-1];
        v[N1+y][v[N1+y].size()-1]->invers=v[x][v[x].size()-1];
    }
    for (int i=1;i<=N1;++i) { // se formeaza arcele adiacente la sursa
        arc *da=new arc;
        arc *daS=new arc;
        da->d=i;
        da->cap=1;
        da->flow=0;
        v[sursa].pb(da);

        daS->d=sursa;
        daS->cap=daS->flow=0;
        v[i].pb(daS);

        v[sursa][v[sursa].size()-1]->invers=v[i][v[i].size()-1];
        v[i][v[i].size()-1]->invers=v[sursa][v[sursa].size()-1];
    }
    for (int i=N1+1;i<=N1+N2;++i) { // se formeaza arcele adiacente la destinatie
        arc *da=new arc;
        arc *daD=new arc;;
        da->d=i;
        da->cap=da->flow=0;
        v[dest].pb(da);

        daD->d=dest;
        daD->cap=1;
        daD->flow=0;
        v[i].pb(daD);

        v[dest][v[dest].size()-1]->invers=v[i][v[i].size()-1];
        v[i][v[i].size()-1]->invers=v[dest][v[dest].size()-1];
    }
    int cuplaj=0;
    while (bfs()) { // algoritmul edmonds-karp optim
        vector<arcp>::iterator it;
        for (it=v[dest].begin();it<v[dest].end();++it) {
            arc *muchie=(*it)->invers;
            if (verif.test((*it)->d) && muchie->cap!=muchie->flow) {
                muchie_from_dad[dest]=muchie;
                int min1=INF;
                for (arc *p=muchie_from_dad[dest];  ;p=muchie_from_dad[(p->invers)->d]) {
                    if ((p->cap)-(p->flow)<min1) {
                        min1=(p->cap)-(p->flow);
                    }
                    if (((p->invers)->d)==sursa) {
                        break;
                    }
                }
                if (min1!=0) {
                    ++cuplaj;
                    for (arc *p=muchie_from_dad[dest];  ;p=muchie_from_dad[(p->invers)->d]) {
                        p->flow++;(p->invers)->flow--;
                        if (((p->invers)->d)==sursa) {
                            break;
                        }
                    }
                }
            }
        }
    }
    g<<cuplaj<<'\n';
    for (int i=1;i<=N1;++i) {
        vector<arc*>::iterator it;
        for (it=v[i].begin();it<v[i].end();++it) {
            if ((*it)->flow==1) {
                g<<i<<' '<<((*it)->d)-N1<<'\n';
            }
        }
    }
}

bool bfs() {
    verif.reset();
    queue<int> Q;
    Q.push(sursa);
    verif.set(sursa,1);
    while (!Q.empty()) {
        int nod=Q.front();
        Q.pop();
        if (nod==dest) {
            return 1;
        }
        vector<arcp>::iterator it;
        for (it=v[nod].begin();it<v[nod].end();++it) {
            if (!verif.test((*it)->d) && (*it)->cap!=(*it)->flow) {
                muchie_from_dad[(*it)->d]=(*it);
                Q.push((*it)->d);
                verif.set((*it)->d,1);
            }
        }
    }
    return 0;
}