Реализация поиска максимального потока методом проталкивания предпотока
Сайт: | Информатикс |
Курс: | Алгоритмы на графах |
Книга: | Реализация поиска максимального потока методом проталкивания предпотока |
Напечатано:: | Гость |
Дата: | Пятница, 18 Июль 2025, 15:28 |
//(C) Igor Kvasov
{поиск максимального потока методом проталкивания предпотока
в его реализации "поднять-и-в начало"}
var
n,m,i,u,v,w,nL,head,vin,vout,oldh,ans:longint;
f,c,e:array[1..100,1..100]of longint;
ne,cur,next,prev,L,s,h:array[1..100]of longint;
procedure Push(u,v:longint);
var
d:longint;
begin
d:=c[u,v]-f[u,v];
if d>s[u] then d:=s[u];
s[u]:=s[u]-d; s[v]:=s[v]+d;
f[u,v]:=f[u,v]+d;
f[v,u]:=-f[u,v];
end;
procedure Lift(u:longint);
var
v:longint;
begin
h[u]:=2*n;
for v:=1 to n do if (c[u,v]-f[u,v]>0)and(h[v]<h[u]) then h[u]:=h[v];
inc(h[u]);
end;
procedure Discharge(u:longint);
begin
while s[u]>0 do begin
v:=e[u,cur[u]];
if v=0 then begin
Lift(u); cur[u]:=1;
end else if (c[u,v]-f[u,v]>0)and(h[u]=h[v]+1) then Push(u,v)
else inc(cur[u]);
end;
end;
begin
read(n,m,vin,vout);
for i:=1 to m do begin
read(u,v,w);
if c[v,u]=0 then begin
inc(ne[u]); e[u,ne[u]]:=v;
inc(ne[v]); e[v,ne[v]]:=u;
end;
c[u,v]:=w;
end;
close(input);
h[vin]:=n;
for v:=1 to n do begin
if c[vin,v]>0 then begin
f[vin,v]:=c[vin,v]; f[v,vin]:=-c[vin,v];
s[v]:=s[v]+c[vin,v];
end;
if (v<>vin)and(v<>vout) then begin
cur[v]:=1;
inc(nL); L[nL]:=v;
end;
end;
for i:=1 to nL do begin
prev[i]:=i-1; next[i]:=i+1;
end;
if nL<>0 then begin
next[nL]:=0;
head:=1; i:=head;
end else i:=0;
while i>0 do begin
u:=L[i];
oldh:=h[u];
Discharge(u);
if (h[u]<>oldh)and(i<>head) then begin
if next[i]<>0 then prev[next[i]]:=prev[i];
next[prev[i]]:=next[i];
next[i]:=head;
prev[i]:=0; prev[head]:=i;
head:=i;
end;
i:=next[i];
end;
ans:=0;
for u:=1 to n do ans:=ans+f[vin,u];
write(ans);
end.
/*********************************************************
Simple implementation of the push-relabel algorithm
for the maximal network flow.
Input format:
n s t - number of nodes, source and sink
then follow c[i][j], if i == j then number is ommited.
See read() function.
*********************************************************/
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <list>
using namespace std;
const int N = 2000;
int e[N],c[N][N],h[N];
int n,s,t;
void push(int u,int v)
{
int f = min(e[u],c[u][v]);
e[u] -= f; e[v] += f;
c[u][v] -= f; c[v][u] += f;
}
void lift(int u)
{
int min = 3 * n + 1;
for (int i = 0;i < n;i++)
if (c[u][i] && (h[i] < min))
min = h[i];
h[u] = min + 1;
}
void discharge(int u)
{
int v = 0;
while (e[u] > 0)
{
if (c[u][v] && h[u] == h[v] + 1)
{
push(u,v); v = 0; continue;
}
v++;
if (v == n)
{
lift(u); v = 0;
}
}
}
void read()
{
cin >> n >> s >> t;
for (int i = 0;i < n;i++)
for (int j = 0;j < n;j++)
{
if (i == j)
continue;
cin >> c[i][j];
}
}
void init()
{
read();
for (int i = 0;i < n;i++)
{
if (i == s)
continue;
e[i] = c[s][i]; c[i][s] += c[s][i];
}
h[s] = n;
}
int main(int argc, char *argv[])
{
list<int> l;
list<int>::iterator cur;
int old;
init();
for (int i = 0;i < n;i++)
if (i != s && i != t)
l.push_front(i);
cur = l.begin();
while (cur != l.end())
{
old = h[*cur];
discharge(*cur);
if (h[*cur] != old)
{
l.push_front(*cur);l.erase(cur);cur = l.begin();
}
cur++;
}
cout << e[t];
return 0;
}