Pagini recente » Cod sursa (job #1655655) | Cod sursa (job #1672242) | Cod sursa (job #1110791) | Borderou de evaluare (job #1569293) | Cod sursa (job #2958804)
/**
* 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;
}