Cod sursa(job #2963379)

Utilizator allee69Aldea Alexia allee69 Data 10 ianuarie 2023 23:05:58
Problema Taramul Nicaieri Scor 0
Compilator cpp-64 Status done
Runda Teme Pregatire ACM Unibuc 2014, Anul I, Semestrul 2 Marime 3.71 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#define INF 1024
using namespace std;

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

//const int INF=1024;
//int maxim=INF;
vector<int> intrare;
vector<int>iesire;
vector<int>dist;


int n, plecare, destinatie;

struct muchie {
    int nod, vec, flux, cap;
};

vector<muchie> v[INF]; //va fi graful generat, in el punem fluxul
muchie tata[INF];
queue<int> q;
vector<muchie> drum;

bool BF()
{
    for(int i=1;i<=n*2+2;i++)
    {
        dist[i]=INF;
        tata[i]={0,0,0};
    }

    dist[plecare] = 0;
    q.push(plecare);

    while(!q.empty())
    {
        int nod= q.front();
        q.pop();
        for(auto i : v[nod])
        {
            if(dist[i.vec] > dist[nod] + 1 && i.flux < i.cap) //putem trimite flux pe aici
            {
                dist[i.vec] = dist[nod] +1;
                tata[i.vec] =i;
                q.push(i.vec);
            }
        }
    }
    if(dist[destinatie] != INF)
        return 1;
    return 0;
}

int main()
{
    dist.resize(INF);
    intrare.resize(INF);
    iesire.resize(INF);

    f>>n;
    //1..n nodurile de pe partea stanga
    //n+1, n+2,....2n nodurile de pe partea dreapta
    //2n+1 - plecare, 2n+2 - destinatie
    plecare = 2*n+1;
    destinatie = 2*n+2;
    int rezultat = 0,x,y;

    for(int i=1;i<=n;i++)
    {
        f>>x>>y;
        iesire[i]=x; intrare[y]=x;
        //tragem liniile 0->i, (n+i)-> 2n+1
        v[plecare].push_back({plecare,i,0,iesire[i]});
        v[i].push_back({i,plecare,0,0});
        v[n+i].push_back({n+i, destinatie,0,intrare[i]});
        v[destinatie].push_back({destinatie,n+i,0,0});
        rezultat =rezultat+ iesire[i];
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=n+1; j<=2*n;j++)
            if(i+n !=j)
                //tragem muchiile (x,y) de capacitate 1 unde x,y sunt diferite
            {
                v[i].push_back({i,j,0,1});
                v[j].push_back({j,i,0,0});
            }
    }
    while(BF()) //cat timp gasim un drum de la 1 la n
    {
        int d= destinatie;
        drum.clear();
        while(tata[d].nod!=0)
        {
            drum.push_back(tata[d]);
            d=tata[d].nod;
        }

        int max= INF; // fluxul maxim pe care il pot trimite pe drumul gasit
        for(auto i:drum) //calculam ce flux poate fi trimis
            max = min(max, i.cap - i.flux);

        for(auto m: drum) //scadem si adunam fluxul pe care il bagam din toate muchiile
        {
            x= m.nod; y=m.vec;
            for(int i=0;i< v[x].size();i++) //gasim muchia (x,y) si adunam fluxul gasit
                if(v[x][i].vec == y)
                {
                    v[x][i].flux+=max;
                    break;
                }

            for(int i=0;i<v[y].size();i++) //gasim muchia (y,x) si scad fluxul bagat
                if(v[y][i].vec==x)
                {
                    v[y][i].flux-=max;
                    break;
                }
        }


    }

    g<<rezultat<<endl;
    for(int i=1;i<=n;i++)
        for(auto j: v[i])
            if(j.flux > 0)
                g<<j.nod<<" "<<j.vec-n<<endl;

    return 0;
}
//complexitate: O(E*F) e-> nr de noduri, f-> flow-ul maxim

//Codul prezentat este alg lui Ford-Fulkerson pentru a gasi flow-ul maxim
//intr-un graf. Fiecare nod are o capacitate. Incepe cu un flow initial si
//cauta de repetate ori un drum cat mai bun. Augmenteaza drumul curent pana
//cand nu mai poate
// vector<muchie> v[inf] este graful cu fluxul, initial va fi 0
//muchie tata[inf] retine parintele fiecarui nod in drum
//q pt BFS
//vector<muchie> drum este vectorul care imi retine nodurile din drum
//bool BF este parcurgerea BFS
//in functia main vom apela BFS si vom updata graful in functie de flow-ul
//maxim gasit.