Cod sursa(job #2958818)

Utilizator Cosmina_GheorgheGheorghe Cosmina Cosmina_Gheorghe Data 28 decembrie 2022 14:59:36
Problema Taramul Nicaieri Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.87 kb
/*#include <iostream>
#include <vector>
#include <fstream>
#include <queue>
#include <algorithm>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
const int d = 15000;
int c[d][d]; //capacitate intre doua noduri
//int f[d][d]; //capacitate consumata
vector<int> la[d]; //lista adiacenta
vector<int> vizitat;
bool am[d];
int tata[d]; //tatal fiecarui nod
int n,m,e,x,y,i,j,sursa,destinatie,z,flow,nod;

int bfs()
{
    vizitat.assign(destinatie+1, 0);
    queue<int> coada;
	coada.push(sursa);
	while(!coada.empty())
    {
        nod=coada.front();
        coada.pop();
        vizitat[nod]=1;
        if(nod == destinatie) break; //opresc parcurgerea daca ajung la destinatie
        for(int j=0;j<la[nod].size();j++)
        {
            if(vizitat[la[nod][j]]==0 && c[nod][la[nod][j]]!=f[nod][la[nod][j]]) //daca nu e vizitat si daca drumul nu a fost consumat
            {
                coada.push(la[nod][j]);
                vizitat[la[nod][j]];
                tata[la[nod][j]]=nod; //retin tatal nodului
            }
        }
    }
    return vizitat[destinatie];//ne zice daca a ajuns la final drumul -> nu s a gasit fluxul maxim deci continuam
}

int main()
{
    fin>>n>>m>>e;
    //transformam in retea de transport folosind sursa si destinatie
    sursa=0;
    destinatie=n+m+1;
    for(i=1;i<=n;i++)
    {
  		la[sursa].push_back(i);
  		la[i].push_back(sursa);
  		c[sursa][i]=1;
    }
    for(i=1;i<=e;i++)
    {
        fin>>x>>y;
  		la[x].push_back(n+y);
  		la[n+y].push_back(x);
  		c[x][n+y]=1;
  		am[y] = true;
    }
    for(i=1;i<=m;i++)
    {
        if (am[i])
        {
            la[n+i].push_back(destinatie);
            la[destinatie].push_back(n+i);
            c[n+i][destinatie]=1;
        }

    }
    flow=0;
    while(bfs())
    {
        for(i=0;i<la[destinatie].size();i++)
        {
            nod = la[destinatie][i];
			if (f[nod][destinatie] == c[nod][destinatie] || !vizitat[nod]) continue;
			tata[destinatie] = nod;
			int minn=9999999;
			for (j = destinatie; j> sursa; j = tata[j])
            {
  				minn = min(minn, c[tata[j]][j] - f[tata[j]][j]); //calculez capacitatea minima a drumului (capacitate totala-consumata)
  			}
			if (minn == 0) continue;
			for (j = destinatie; j> sursa; j = tata[j]) //modific capacitatile drumurilor+ maresc flowul rezidual
            {
  				f[tata[j]][j] += minn;
  				f[j][tata[j]] -= minn;
  			}
  			flow=flow+minn;
        }
    }
    fout<<flow<<"\n";
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            if(f[i][j+n]==1)
            {
                fout<<i<<" "<<j<<"\n";
            }
        }
    }
    return 0;
}*/
#include <vector>
#include <fstream>
#include <queue>
#include <algorithm>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
const int d = 25000;
vector<pair<int,pair<long long int,int>>> la[d]; //am nodul catre care merg, capacitatea actuala si pozitia primului elememnt in lista celui de al doilea
vector<int> vizitat;
bool am[d];
pair<int, int> tata[d];
vector<pair<int,int>> in_destinatie;//retin toate nodurile care ajung in destinatie ca sa le pot parcurge ulterior
int n,m,e,x,y,i,j,sursa,destinatie,z,flow,nod;

int bfs()
{
    vizitat.assign(destinatie+1, 0);
    queue<int> coada;
	coada.push(sursa);
	tata[sursa] = {-1, -1};
	while(!coada.empty())
    {
        nod=coada.front();
        coada.pop();
        vizitat[nod]=1;
        if(nod == destinatie) break; //opresc parcurgerea daca ajung la destinatie
        for(int j=0;j<la[nod].size();j++)
        {
            if(vizitat[la[nod][j].first]==0 && la[nod][j].second.first>0) //daca nu e vizitat si daca drumul e valid
            {
                coada.push(la[nod][j].first);
                vizitat[la[nod][j].first];
                tata[la[nod][j].first]={nod,j}; //retin tatal nodului si pozitia nodului in lista sa
            }
        }
    }
    return vizitat[destinatie];//ne zice daca a ajuns la final drumul -> nu s a gasit fluxul maxim deci continuam
}

int main()
{
    fin>>n>>m>>e;
    //transformam in retea de transport folosind sursa si destinatie
    sursa=0;
    destinatie=n+m+1;
    for(i=1;i<=n;i++)
    {
        la[sursa].push_back({i, {1, 0}});
        la[i].push_back({sursa, {0, 0}});
        la[sursa][la[sursa].size() - 1].second.second = la[i].size()-1;//salvez pozitia lui x in lista lui y pt rezid
        la[i][la[i].size() - 1].second.second = la[sursa].size()-1; //invers
    }
    for(i=1;i<=e;i++)
    {
        fin>>x>>y;
  		la[x].push_back({n+y, {1, 0}});
        la[n+y].push_back({x, {0, 0}});
  		am[y] = true;
  		la[x][la[x].size() - 1].second.second = la[y+n].size()-1;//salvez pozitia lui x in lista lui y
        la[y+n][la[y+n].size() - 1].second.second = la[x].size()-1; //invers
    }
    for(i=1;i<=m;i++)
    {
        if (am[i])
        {
            la[destinatie].push_back({n+i, {0, 0}});
            la[n+i].push_back({destinatie, {1, 0}});
            in_destinatie.push_back({n+i, la[n+i].size() - 1});
            la[n+i][la[n+i].size() - 1].second.second = la[destinatie].size()-1;//salvez pozitia lui x in lista lui y
            la[destinatie][la[destinatie].size() - 1].second.second = la[n+i].size()-1; //invers
        }

    }
    pair<int, int> nod2;
    flow=0;
    while(bfs())
    {
        for (auto y:in_destinatie) //ma uit la fiecare nod care are legatura directa cu destinatia
        {
            tata[destinatie] = y;
            nod2 = tata[destinatie];
            int catre = destinatie;
            long long int minn = 1000000;
            //trec prin tot drumul de la coada la sursa
            while (nod2.first != -1)
            {

                minn = min(minn, la[nod2.first][nod2.second].second.first);  //folosesc scrierea asta ca sa pot accesa in sens invers
// distanta fata de un fiu de pe o anumita pozitie
                nod2 = tata[nod2.first];
            }

            flow=flow+ minn;
            nod2 = tata[destinatie];
            //modific capacitatile drumurilor
            while (nod2.first != -1) {
                int poz = la[nod2.first][nod2.second].second.second;
                la[nod2.first][nod2.second].second.first -= minn; //capacitatea normala scade
                la[catre][poz].second.first += minn; //capacitatea reziduala se mareste (drumul invers)
                catre = nod2.first;
                nod2 = tata[nod2.first];
            }
        }

    }
    fout<<flow<<"\n";
    for (i=1; i<=n; i++) {
        for (int j=0;j<la[i].size();j++) {
            if (la[i][j].first != 0 && la[i][j].second.first == 0) //daca nu e sursa si daca a fost consumata capacitatea(adica e 0)
            {
                fout<<i<<" "<<la[i][j].first-n<<"\n";
            }
        }
    }
    return 0;
}