Hướng dẫn cho Luồng Cực Đại Trên Mạng


Chỉ sử dụng khi thực sự cần thiết như một cách tôn trọng tác giả và người viết hướng dẫn này.

Chép code từ bài hướng dẫn để nộp bài là hành vi có thể dẫn đến khóa tài khoản.

Authors: uou

Các code dưới đây có thể không AC được bài này nên các bạn chỉ tham khảo, tuyệt đối không được chép code, nếu phát hiện sẽ có thể bị ban.

Code Pascal
Delphi
{$MODE DELPHI}
program maxflow;
const
  input  = '';
  output = '';
  maxn = 1000;
type
  PNode = ^TNode;
  TNode = record
    adj: integer;
    link: PNode;
  end;
var
  c,f: array[1..maxn,1..maxn] of integer;
  trace,queue: array[1..maxn] of integer;
  n,m,s,t: integer;
  a: array[1..maxn] of PNode;

procedure add(u,v: integer);
var
  P: PNode;
begin
  New(P);
  P^.adj := v;
  P^.link := a[u];
  a[u] := P;
end;

procedure init;
var
  fi: text;
  i,u,v: integer;
begin
  assign(fi, input);
    reset(fi);

  readln(fi, n, m, s, t);
  fillchar(c, sizeof(c), 0);
  fillchar(f, sizeof(f), 0);

  for i := 1 to m do
    begin
      readln(fi, u, v, c[u,v]);
      add(u,v);
    end;

  close(fi);
end;

function FindPath: boolean;
var
  va,st,front,rear: integer;
  u: PNode;
begin
  fillchar(trace, sizeof(trace), 0);
  front := 1;
  rear := 1;
  queue[1] := s;
  trace[s] := -1;

  repeat
    st := queue[front];
    inc(front);
    u := a[st];

    while u <> nil do
      begin
        va := u^.adj;
        if (trace[va] = 0) and (c[st,va] > f[st,va]) then
          begin
            trace[va] := st;
            if va = t then exit(true);

            inc(rear);
            queue[rear] := va;
          end;

        u := u^.link;
      end;
  until front > rear;
  FindPath := false;
end;

procedure IncFlow;
var
  delta,u,v: integer;
begin
  delta := high(longint);
  v := t;

  repeat
    u := trace[v];
    if c[u,v] - f[u,v] < delta then delta := c[u,v] - f[u,v];
    v := u;
  until v = s;

  v := t;
  repeat
    u := trace[v];
    f[u,v] := f[u,v] + delta;
    f[v,u] := f[v,u] - delta;
    v := u;
  until v = s;
end;

procedure FordFulkerson;
begin
  repeat
    if not FindPath then break;
    IncFlow;
  until false;
end;

procedure printresult;
var
  fo: text;
  cost,i,j: integer;
begin
  assign(fo, output);
    rewrite(fo);

  cost := 0;
  for i := 1 to n do
    if f[s,i] > 0 then cost := cost + f[s,i];

  writeln(fo, cost);
  close(fo);
end;

begin
  init;
  FordFulkerson;
  printresult;
end.
Code C++
C++
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int oo = 1 << 29;

struct edge
{
    int x, y, cap, flow;
};

struct Flow
{
    int n, S, T;
    vector < vector <int> > a;
    vector <int> cur, d;
    vector <edge> e;

    Flow() {}
    Flow(int _n, int _S, int _T)
    {
        n = _n; S = _S; T = _T;
        a = vector < vector <int> >(n + 1);
        cur = vector <int>(n + 1);
        d = vector <int>(n + 1);
    }

    void addEdge(int x, int y, int _cap)
    {
        edge e1 = {x, y, _cap, 0};
        edge e2 = {y, x, 0, 0};
        a[x].push_back(e.size()); e.push_back(e1);
        a[y].push_back(e.size()); e.push_back(e2);
    }

    int bfs()
    {
        queue <int> q;
        for (int i = 1; i <= n; i++) d[i] = -1;
        q.push(S); d[S] = 0;
        while (!q.empty() && d[T] < 0)
        {
            int x = q.front(); q.pop();
            for (int i = 0; i < int(a[x].size()); i++)
            {
                int id = a[x][i], y = e[id].y;
                if (d[y] < 0 && e[id].flow < e[id].cap)
                    q.push(y), d[y] = d[x] + 1;
            }
        }
        return d[T] >= 0;
    }

    int dfs(int x, int val)
    {
        if (!val) return 0;
        if (x == T) return val;
        for (; cur[x] < int(a[x].size()); cur[x]++)
        {
            int id = a[x][cur[x]], y = e[id].y;
            if (d[y] != d[x] + 1) continue;
            int pushed = dfs(y, min(val, e[id].cap - e[id].flow));
            if (pushed)
            {
                e[id].flow += pushed;
                e[id ^ 1].flow -= pushed;
                return pushed;
            }
        }
        return 0;
    }

    int maxFlow()
    {
        int res = 0;
        while (bfs())
        {
            for (int i = 1; i <= n; i++) cur[i] = 0;
            while (1)
            {
                int val = dfs(S, oo);
                if (!val) break;
                res += val;
            }
        }
        return res;
    }   
};

int main()
{
    int n, m, S, T, x, y, z;
    cin >> n >> m >> S >> T;
    Flow u(n, S, T);
    while (m--)
    {
        scanf("%d%d%d", &x, &y, &z);
        u.addEdge(x, y, z);
    }
    cout << u.maxFlow() << endl;
}
Code Python
Python
import sys
from collections import deque

sys.setrecursionlimit(200000)

INF = 10**9

class Edge:
    def __init__(self, u, v, capacity, flow=0):
        self.u = u
        self.v = v
        self.capacity = capacity
        self.flow = flow

class Network:
    def __init__(self, n, s, t):
        self.n = n
        self.source = s
        self.sink = t
        self.a = [[] for _ in range(n + 1)]
        self.E = []
        self.cur = [0] * (n + 1)
        self.dist = [-1] * (n + 1)

    def addEdge(self, u, v, c):
        self.a[u].append(len(self.E))
        self.E.append(Edge(u, v, c, 0))
        self.a[v].append(len(self.E))
        self.E.append(Edge(v, u, 0, 0))

    def bfs(self):
        self.dist = [-1] * (self.n + 1)
        self.dist[self.source] = 0
        Q = deque([self.source])

        while Q:
            u = Q.popleft()
            for idx in self.a[u]:
                edge = self.E[idx]
                v = edge.v
                if self.dist[v] == -1 and edge.flow < edge.capacity:
                    self.dist[v] = self.dist[u] + 1
                    Q.append(v)

        return self.dist[self.sink] != -1

    def dfs(self, u, flow):
        if flow == 0 or u == self.sink:
            return flow

        while self.cur[u] < len(self.a[u]):
            idx = self.a[u][self.cur[u]]
            edge = self.E[idx]
            v = edge.v

            if self.dist[v] != self.dist[u] + 1:
                self.cur[u] += 1
                continue

            delta = self.dfs(v, min(flow, edge.capacity - edge.flow))
            if delta > 0:
                edge.flow += delta
                self.E[idx ^ 1].flow -= delta
                return delta

            self.cur[u] += 1

        return 0

    def maxFlow(self):
        ans = 0
        while self.bfs():
            self.cur = [0] * (self.n + 1)
            while True:
                delta = self.dfs(self.source, INF)
                if delta == 0:
                    break
                ans += delta
        return ans

def main():
    input = sys.stdin.readline

    try:
        line = input().split()
        if not line:
            return
        n, m, s, t = map(int, line)

        G = Network(n, s, t)

        for _ in range(m):
            u, v, c = map(int, input().split())
            G.addEdge(u, v, c)

        print(G.maxFlow())
    except ValueError:
        pass

if __name__ == "__main__":
    main()

Bình luận

Mới nhất
Tải bình luận...

Không có bình luận nào.