Cod sursa(job #2820743)

Utilizator ionut31Ioan Ionescu ionut31 Data 21 decembrie 2021 13:03:48
Problema Critice Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.05 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>

#define inf 1000000009

using namespace std;


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

//listele de adiacenta
vector<vector<int>> la;

//matricele de flux si capacitate
vector<vector<int>> flux;
vector<vector<int>> capacitate;


int n,m;

//vectorul de muchii care ajuta la retinerea indicelui fiecarei muchii
vector<pair<int,int>> muchii;

//vectorii tati si vizitat folositi in parcurgerea bfs
vector<int> tati;
vector<int> vizitat;


bool BfsMaxFlow(int S, int D)
{
    //complexitatea algoritmului este O(n)
    tati[D] = 0;
    //golesc vectorul vizitat la fiecare parcurgere
    vizitat.clear();
    //redimensionam vectorul vizitat si il initializam
    vizitat.resize(n+1, 0);

    //coada folosita in parcurgerea Bfs
    queue<int> q;

    //punem in coada nodul de start
    q.push(S);
    tati[S] = 0;
    vizitat[S] = true;
    //cat timp coada nu este goala(mai am elemente de procesat) si nu s-a ajunj inca in destinatie
    //parcurg Bfs
    while(!q.empty() && tati[D] == 0)
    {
        //luam urmatorul element din coada
        int x = q.front();
        q.pop();

        //ii parcurgem lista de adiacenta
        for(int i=0; i<la[x].size(); ++i)
        {
            int y = la[x][i];

            //daca nodul adiacent curent nu a fost vizitat si arcul de la x la y este unul nesaturat
            if(vizitat[y] == true || capacitate[x][y] == flux[x][y])
                continue;

            tati[y] = x;
            vizitat[y] = true;
            q.push(y);
        }
    }

    if(tati[D]!=0)
        return true;
    else
        return false;

}


int MaxFlow(int S, int D)
{
    //complexitatea algoritmului este O(n*(m^2))

    //golesc vectorul tati
    tati.clear();
    //redimensionam vectorul tati si il initializam
    tati.resize(n+1, 0);

    int rez = 0;

    //dimensionam si initializam matricea flux
    flux.resize(n+1, vector<int>(n+1, 0));

    //cat timp gasesc un drum de ameliorare de la sursa la destinatie
    while(BfsMaxFlow(S, D))
    {

        for(int i=0; i<la[D].size(); ++i)
        {
            int y = la[D][i];
            if (flux[y][D] == capacitate[y][D] || !vizitat[y])
                continue;

            tati[D] = y;
            int a = inf;
            //parcurg drumul de la D la S pentru a determina cu cat se poate modifica fluxul pe acel drum
            for (int i = D; i != S; i = tati[i])
                a = min(a, capacitate[tati[i]][i] - flux[tati[i]][i]);

            if (a == 0)
                continue;
            //parcurg din nou drumul pentru a face actualizarea
            for (int i = D; i != S; i = tati[i])
            {
                flux[tati[i]][i] += a;
                flux[i][tati[i]] += a;

            }
            rez += a;
        }
    }

    return rez;
}



void Dfs1(int nod, vector<int> &vizitat)
{
    vizitat[nod] = 1;

    for(int i = 0; i < la[nod].size(); ++i)
    {
        int y = la[nod][i];
        if(vizitat[y] == 0 && capacitate[nod][y] > flux[nod][y]) //doar muchiile nesaturate
        {
            Dfs1(y, vizitat);
        }
    }
}

//void Dfs2(int nod, vector<int> &vizitat)
//{
//    vizitat[nod] = 1;
//
//    for(int i = 0; i < la[nod].size(); ++i)
//    {
//        int y = la[nod][i];
//        if(vizitat[y] == 0 && capacitate[y][nod] > flux[y][nod]) //doar muchiile nesaturate
//        {
//            Dfs2(y, vizitat);
//        }
//    }
//}

int main()
{
    fin >> n >> m;

    //dimensionam matricea capacitate
    capacitate.resize(n+1, vector<int>(n+1, 0));

    //dimensionam vectorul muchii
    muchii.resize(m+1);

    //dimensionam listele de adiacenta
    la.resize(n+1);

    for(int i = 0; i < m; ++i)
    {
        int x, y, c;

        fin >> x >> y >> c;

        //completam listele de adiacenta
        la[x].push_back(y);
        la[y].push_back(x);

        //completam vectorul de muchii
        muchii[i].first = x;
        muchii[i].second = y;

        //completam matricea de capacitati
        capacitate[x][y] = c;
        capacitate[y][x] = c;
    }

    //impingem fluxul maxim posibil prin retea
    MaxFlow(1, n);

    vector<int> vizitat1(n+1);
    //vector<int> vizitat2(n+1);
    vector<int> rezultat;


    //aflam muchiile pentru care daca marim capacitatile obtinem un flux maxim mai mare pentru reteaua data
    Dfs1(1, vizitat1);
    //Dfs2(n, vizitat2);


    for(int i = 0; i < m; ++i)
    {
        int x = muchii[i].first;
        int y = muchii[i].second;

        if((vizitat1[x] && !vizitat1[y]) || (vizitat1[y] && !vizitat1[x]))
            rezultat.push_back(i+1);
//        if((vizitat1[x] && vizitat2[y]) || (vizitat1[y] && vizitat2[x]))
//            rezultat.push_back(i+1);

    }

    int nr = rezultat.size();
    fout << nr << "\n";

    for(int i = 0; i < nr; ++i)
        fout << rezultat[i] << "\n";

    return 0;
}