Cod sursa(job #2958804)

Utilizator popashtefan10Popa Stefan popashtefan10 Data 28 decembrie 2022 13:19:46
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.1 kb
/**
 * 1. Fac BFS cat timp exista un drum de ameliorare
 * 2. BFS gaseste cat mai multe drumuri de ameliorare disjuncte
 * 3. Pentru fiecare drum de ameliorare pompez fluxul minim gasit pe drum
 */

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

const int NMAX = 1024;

int n, m;
int source, destination;
int capacity[NMAX][NMAX], flow[NMAX][NMAX];
int dad[NMAX]; // dad[i] = parintele lui i in arborele BFS
bool visited[NMAX]; // visited[i] = daca a fost vizitat nodul i in BFS
vector<int> adjList[NMAX];

void read() {
  int a, b, c;
  
  scanf("%d %d", &n, &m);
  source = 1;
  destination = n;
  for(int i = 1; i <= m; i++) {
    scanf("%d %d %d", &a, &b, &c);
    // adaug muchia directa (a, b) de capacitate c si muchia inversa (b, a) de capacitate 0
    capacity[a][b] = c;
    adjList[a].push_back(b);
    adjList[b].push_back(a);
  }
}

// creeaza arborele BFS prin vectorul de tati si intoarce daca a gasit macar un drum de ameliorare sau nu
bool bfs() {
  for(int i = 1; i <= n; i++)
    dad[i] = -1;

  bool reachedDestination = false; // daca am ajuns la destinatie printr-un drum de ameliorare  
  queue<int> q;
  q.push(source);
  while(!q.empty()) {
    int crt = q.front();
    q.pop();

    for(int ngh: adjList[crt]) {
      // caut muchii in care mai pot adauga flux si care ajung in noduri nevizitate
      if(ngh == source || dad[ngh] != -1 || capacity[crt][ngh] == flow[crt][ngh])
        continue;
      // daca am ajuns la destinatie nu memorez nodul din care am ajuns pentru ca pot avea mai multe drumuri
      if(ngh == destination) {
        reachedDestination = true;
        continue;
      }

      dad[ngh] = crt;
      q.push(ngh);
    }
  }

  return reachedDestination;
}

// adaug flux pe muchia (node1, node2)
void addEdgeFlow(int node1, int node2, int addedFlow) {
  flow[node1][node2] += addedFlow;
  flow[node2][node1] -= addedFlow;
}

// adauga flux pe drumurile de ameliorare gasite de BFS si intoarce fluxul adaugat
int addFlow() {
  int totalFlow = 0; // fluxul adaugat pe toate drumurile
  // caut capetele drumurilor de ameliorare gasite
  for(int node: adjList[destination]) {
    if((node != source && dad[node] == -1) || capacity[node][destination] == flow[node][destination])
      continue;

    // incep sa parcurg drumul invers ca sa vad cat flux pot adauga
    int crt = node; 
    int canAdd = capacity[node][destination] - flow[node][destination]; // fluxul maxim pe care pot sa il adaug pe acest drum
    while(crt != source) {
      int prev = dad[crt];
      canAdd = min(canAdd, capacity[prev][crt] - flow[prev][crt]);
      crt = prev;
    }

    // adaug fluxul pe drum
    crt = node;
    addEdgeFlow(node, destination, canAdd);
    while(crt != source) {
      int prev = dad[crt];
      addEdgeFlow(prev, crt, canAdd);
      crt = prev;
    }

    totalFlow += canAdd;
  }

  return totalFlow;
}

int main() {
  freopen("maxflow.in", "r", stdin);
  freopen("maxflow.out", "w", stdout);

  read();

  int maxFlow = 0;
  // cat timp gasesc drumuri de ameliorare inseamna ca pot sa mai adaug flux
  while(bfs())
    maxFlow += addFlow();

  printf("%d", maxFlow);

  return 0;
}