Cod sursa(job #1268312)

Utilizator pintilie.andreiPintilie pintilie.andrei Data 20 noiembrie 2014 20:23:12
Problema Flux maxim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.13 kb
#include <fstream>
#define NMAX 1010
#include <queue>

using namespace std;

ifstream fin("maxflow.in");
ofstream fout("maxflow.out");

struct elem{int vecin;int c;int f;} M[NMAX][NMAX],MT[NMAX][NMAX];
int grad_plecare[NMAX],grad_intrare[NMAX],use[NMAX],v[NMAX];
int n,m,indice;
int v1,v2,v_final;
queue <int> C;

void ameliorare_lant();
int BFS();
void curata();
int minim(int a,int b)
{
    if(a<b) return a;
    return b;
}
int vecini(int a,int b,int c);

int main()
{
    int i,x,y,c,s=0;
    fin >> n >> m;
    for(i=1;i<=m;i++)
    {
        fin >> x >> y >> c;
        grad_plecare[x]++;
        M[x][grad_plecare[x]].vecin=y;
        M[x][grad_plecare[x]].c=c;

        grad_intrare[y]++;
        MT[y][grad_intrare[y]].vecin=x;
        MT[y][grad_intrare[y]].c=c;

    }
    while(BFS())//1 daca am atins si 0 daca nu nodul de final
    {
        //in v determin vectorul de marcaje in BFS
        ameliorare_lant();
        //ameliorare lant si sterg marcaje pt tura viitoare

    }
    for(i=1;i<=grad_intrare[n];i++)
        s+=MT[n][i].f;
    fout << s <<'\n';
    return 0;
}

void ameliorare_lant()
{
    int i,curent=n,unde,poz,cat;
    v1=99999999;
    v2=99999999;
    for(i=1;i<=indice;i++)//3 6 1 exemplu
    {
        if(v[i]>0)
        {
            unde=v[i];//daca e pozitiv
            //arc 3->4
            poz=vecini(unde,curent,1);
            cat=M[unde][poz].c-M[unde][poz].f;
            if(cat<v1)
                v1=cat;
        }
        else
        {
            unde=-v[i];
            poz=vecini(unde,curent,2);
            //arc 3<-4
            cat=MT[unde][poz].f;
            if(cat<v2)
                v2=cat;
        }
        curent=unde;
    }
    v_final=minim(v1,v2);
    //acum actualizez
    curent=n;
    for(i=1;i<=indice;i++)
    {
        if(v[i]>0)
        {
            unde=v[i];//daca e pozitiv
            //arc 3->4
            poz=vecini(unde,curent,1);
            M[unde][poz].f+=v_final;
            poz=vecini(curent,unde,2);
            MT[curent][poz].f+=v_final;
        }
        else
        {
            unde=-v[i];
            poz=vecini(unde,curent,2);
            //arc 3<-4
            MT[unde][poz].f-=v_final;
             poz=vecini(curent,unde,1);
            M[curent][poz].f-=v_final;
        }
        curent=unde;
    }
}

int vecini(int a,int b,int tip)
{//plec de la a la b de tip 1(adica umblu in M cu grad_plecare) si de tip 2(umblu in MT cu grad_intoarcere)
    int i;
    if(tip==1)
    {
        for(i=1;i<=grad_plecare[a];i++)
            if(M[a][i].vecin==b)
                return i;
    }
    else
    {
        for(i=1;i<=grad_intrare[a];i++)
            if(MT[a][i].vecin==b)
             return i;
    }
    return 0;
}

int BFS()
{
    int i,val,ok;
    //intotdeauna plec din 1
    curata();//coada si use
    C.push(1);
    use[1]=1;
    ok=1;
    while(C.size()!=0 && ok==1)
    {
        val=C.front();
        C.pop();
        for(i=1;i<=grad_plecare[val];i++)
            if(use[M[val][i].vecin]==0 && M[val][i].f!=M[val][i].c)
            {
                use[M[val][i].vecin]=val;
                C.push(M[val][i].vecin);
                if(i==n)
                {
                    ok=0;
                    break;
                }
            }
        for(i=1;i<=grad_intrare[val];i++)
            if(use[MT[val][i].vecin]==0 && MT[val][i].f!=MT[val][i].c)
            {
                use[MT[val][i].vecin]=-val;
                C.push(MT[val][i].vecin);
                if(i==n)
                {
                    ok=0;
                    break;
                }

            }
    }
    if(use[n]!=0)
    {
        //reconstruiesc drumul si ies
        val=use[n];
        indice=1;
        while(val!=1)
        {
            v[indice]=val;
            indice++;
            if(val<0) val=-val;//nu is sigur aici
            val=use[val];
        }
        v[indice]=val;
        return 1;
    }
    return 0;
}

void curata()
{
    int i;
    while(C.size())
        C.pop();
    for(i=1;i<=n;i++)
        use[i]=0;
}