Editorial for Trao đổi thông tin


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int oo = 1000111222;

vector <int> path;

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

struct MinCostMaxFlow
{
    int n, S, T;
    vector < vector <int> > a;
    vector <int> dist, prev, done, pot;
    vector <edge> e;

    MinCostMaxFlow() {}
    MinCostMaxFlow(int _n, int _S, int _T)
    {
        n = _n; S = _S; T = _T;
        a = vector < vector <int> >(n + 1);
        dist = vector <int>(n + 1);
        prev = vector <int>(n + 1);
        done = vector <int>(n + 1);
        pot = vector <int>(n + 1, 0);
    }

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

    pair <int,int> dijkstra()
    {
        int flow = 0, cost = 0;
        for (int i = 1; i <= n; i++) done[i] = 0, dist[i] = oo;
        priority_queue < pair<int,int> > q;
        dist[S] = 0; prev[S] = -1;
        q.push(make_pair(0, S));
        while (!q.empty())
        {
            int x = q.top().second; q.pop();
            if (done[x]) continue;
            done[x] = 1;
            for (int i = 0; i < int(a[x].size()); i++)
            {
                int id = a[x][i], y = e[id].y;
                if (e[id].flow < e[id].cap)
                {
                    int D = dist[x] + e[id].cost + pot[x] - pot[y];
                    if (!done[y] && D < dist[y])
                    {
                        dist[y] = D; prev[y] = id;
                        q.push(make_pair(-dist[y], y));
                    }
                }
            }
        }

        for (int i = 1; i <= n; i++) pot[i] += dist[i];

        if (done[T])
        {
            flow = oo;
            for (int id = prev[T]; id >= 0; id = prev[e[id].x]) 
                flow = min(flow, e[id].cap - e[id].flow);
            for (int id = prev[T]; id >= 0; id = prev[e[id].x]) 
            {
                cost += e[id].cost * flow;
                e[id].flow += flow;
                e[id ^ 1].flow -= flow;
            }
        }

        return make_pair(flow, cost);
    }

    pair <int,int> minCostMaxFlow()
    {
        int totalFlow = 0, totalCost = 0;
        while (1)
        {
            pair <int,int> u = dijkstra();
            if (!done[T]) break;
            totalFlow += u.first; totalCost += u.second;
        }
        return make_pair(totalFlow, totalCost);
    }

    void trace(int x)
    {
        if (x == T)
        {
            cout << path.size();
            for (int i = 0; i < int(path.size()); i++) cout << ' ' << path[i];
            puts("");
            return;
        }
        path.push_back(x);
        for (int i = 0; i < int(a[x].size()); i++)
        {
            int id = a[x][i];
            if (e[id].flow > 0) 
            {
                if (e[id].y < T) e[id].flow = 0;
                trace(e[id].y);
                return;
            }
        }
    }
};

int main()
{
    int n, m, F, s, t, x, y, z;
    cin >> n >> m >> F >> s >> t;
    int S = n + 1, T = n + 2;
    MinCostMaxFlow u(T, S, T);
    while (m--) cin >> x >> y >> z, u.addEdge(x, y, 1, z), u.addEdge(y, x, 1, z);
    u.addEdge(S, s, F, 0);
    u.addEdge(t, T, F, 0);
    pair <int,int> ans = u.minCostMaxFlow();
    if (ans.first < F) puts("-1");
    else 
    {
        cout << ans.second << endl;
        while (F--) path.clear(), u.trace(s);
    }
}

Code mẫu của happyboy99x

#include<bits/stdc++.h>
using namespace std;

#define TR(v,i) for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
const int N = 100, INF = 1e9;
vector<pair<int, int> > g[N+2];
vector<int> c, cost, f;
int n, m, k, s, t;

void addEdge(int u, int v, int cst, int lim) {
    g[u].push_back(make_pair(v, c.size()));
    g[v].push_back(make_pair(u, c.size()+1));
    c.push_back(lim); c.push_back(0);
    cost.push_back(cst); cost.push_back(-cst);
    f.push_back(0); f.push_back(0);
}

pair<int, int> mincost(int s, int t, int n) {
    int totalcost = 0, maxf = 0;
    while(true) {
        vector<int> d (n, INF);
        vector<pair<int, int> > tr (n, make_pair(INF, INF));
        vector<bool> inq (n, false);
        queue<int> q;
        d[s] = 0; q.push(s); inq[s] = true; tr[s] = make_pair(-1, -1);
        while(!q.empty()) {
            int u = q.front(); q.pop(); inq[u] = false;
            TR(g[u], it) {
                int v = it->first, e = it->second;
                if(c[e] > f[e] && d[v] > d[u] + cost[e]) {
                    d[v] = d[u] + cost[e];
                    tr[v] = make_pair(u, e);
                    if(!inq[v]) q.push(v), inq[v] = true;
                }
            }
        }
        if(d[t] == INF) break;
        int delta = INF;
        for(int u = tr[t].first, v = t; u != -1; v = u, u = tr[u].first)
            delta = min(delta, c[tr[v].second] - f[tr[v].second]);
        for(int u = tr[t].first, v = t; u != -1; v = u, u = tr[u].first) {
            f[tr[v].second] += delta;
            f[tr[v].second ^ 1] -= delta;
        }
        maxf += delta; totalcost += d[t] * delta;
    }
    return make_pair(maxf, totalcost);
}

void dfs(int s, int t, vector<int> &v, vector<bool> &used) {
    v.push_back(s);
    if(s == t) {
        cout << v.size();
        TR(v, i) cout << ' ' << *i+1;
        cout << '\n';
    } else {
        TR(g[s], it) {
            int u = it->first, e = it->second;
            if(!used[e] && c[e] == 1 && c[e] == f[e]) {
                used[e] = true;
                dfs(u, t, v, used);
                break;
            }
        }
    }
    v.pop_back();
}

void printRemain() {
    for(int u = 0; u < n; ++u) {
        TR(g[u], it) {
            int v = it->first, e = it->second;
            if(c[e] == 1 && f[e] == 1)
                cerr << "Remain " << u+1 << ' ' << v+1 << endl;
        }
    }
}

void enter() {
    cin >> n >> m >> k >> s >> t; --s; --t;
    for(int i = 0; i < m; ++i) {
        int u, v, c; cin >> u >> v >> c; --u; --v;
        addEdge(u, v, c, 1);
        addEdge(v, u, c, 1);
    }
    addEdge(n, s, 0, k);
    addEdge(t, n+1, 0, k);
}

int main() {
    ios::sync_with_stdio(false);
    enter();
    pair<int, int> res = mincost(n, n+1, n+2);
    if(res.first < k) cout << -1 << '\n';
    else {
        cout << res.second << '\n';
        vector<int> tmp;
        vector<bool> used (c.size(), false);
        for(int i = 0; i < k; ++i) dfs(s, t, tmp, used);
    }
    return 0;
}

Code mẫu của ladpro98

#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstdlib>
#include <ctime>
#include <memory.h>
#include <cassert>

#define FOR(i, a, b) for(int i = (a); i < (b); ++i)
#define REP(i, a, b) for(int i = (a); i <=(b); ++i)
#define FORD(i, a, b) for(int i = (a); i > (b); --i)
#define REPD(i, a, b) for(int i = (a); i >=(b); --i)
#define TR(it, a) for(__typeof(a.begin()) it = a.begin(); it != a.end(); ++it)
#define RESET(a, v) memset(a, (v), sizeof(a))
#define SZ(a) (int(a.size()))
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair
#define LL long long
#define LD long double
#define II pair<int, int>
#define X first
#define Y second
#define VI vector<int>
#define VII vector<II>
#define endl '\n'

const int N = 111;
const int INF = INT_MAX;

using namespace std;

int T[N], d[N];
bool inQ[N], was[N][N];
int cap[N][N], cost[N][N], flow[N][N];
int n, m, source, sink, minCost, maxFlow;

bool findPath() {
  queue<int> Q;
  REP(i, 1, n) {
    T[i] = inQ[i] = 0; d[i] = INF;
  }
  Q.push(source); inQ[source] = 1; d[source] = 0;
  while (!Q.empty()) {
    int u = Q.front(); Q.pop(); inQ[u] = 0;
    REP(v, 1, n)
    if (flow[u][v] < cap[u][v]) {
      int uv = cost[u][v] * (flow[u][v] < 0 ? -1: 1);
      if (d[v] > d[u] + uv) {
        d[v] = d[u] + uv;
        T[v] = u;
        if (!inQ[v]) {
          inQ[v] = 1;
          Q.push(v);
        }
      }
    }
  }
  return d[sink] < INF;
}

void incFlow() {
  int delta = INF;
  for (int v = sink, u = T[v]; v != source; v = u, u = T[v])
    delta = min(delta, flow[u][v] < 0 ? -flow[u][v] : (cap[u][v] - flow[u][v]));
  for (int v = sink, u = T[v]; v != source; v = u, u = T[v])
    flow[u][v] += delta, flow[v][u] -= delta;
  maxFlow += delta;
  minCost += delta * d[sink];
}

VI path;

void go(int u) {
  path.PB(u);
  REP(v, 1, n)
  if (flow[u][v] > 0 && !was[u][v]) {
    was[u][v] = 1; go(v); break;
  }
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  #ifdef _LAD_
    freopen("KWAY.in", "r", stdin);
  #endif // _LAD_
  cin >> n >> m >> maxFlow >> source >> sink;
  int u, v;
  FOR(i, 0, m) {
    cin >> u >> v; cin >> cost[u][v];
    cost[v][u] = cost[u][v];
    cap[u][v] = cap[v][u] = 1;
  }
  ++n;
  cap[n][source] = maxFlow;
  int S = source; source = n;
  int kway = maxFlow; maxFlow = 0;
  while (findPath()) incFlow();
  if (maxFlow < kway) cout << -1 << endl;
  else {
    cout << minCost << endl;
    while (kway--) {
      path.clear();
      go(S);
      cout << SZ(path) << ' ';
      for (int it: path)
        cout << it << ' ';
      cout << endl;
    }
  }
  return 0;
}

Code mẫu của RR

{$R+,Q+}
PROGRAM KWAY;
CONST
  fi='';
  fo='';
  maxn=100;
  max=1000000001;
VAR
  n,s,t:integer;
  k:integer;
  c:array[1..maxn,1..maxn] of longint;
  d:array[1..maxn,1..maxn] of byte;
  pre:array[1..maxn] of shortint;
  min:array[1..maxn] of longint;
Procedure ReadInput;
Var
  f:text;
  m,i:integer;
  u,v:integer;
Begin
  Assign(f,fi); Reset(f);
  Readln(f,n,m,k,s,t);
  For u:=1 to n do
    For v:=1 to n do
      c[u,v]:=max;
  For u:=1 to n do c[u,u]:=0;
  For i:=1 to m do
    begin
      Readln(f,u,v,c[u,v]);
      c[v,u]:=c[u,v];
    end;
  Close(f);
End;
Function min2(a,b:longint):longint;
Begin
  If a<b then min2:=a else min2:=b;
End;
Procedure KhoiTri;
Var
  i:integer;
Begin
  For i:=1 to n do
    min[i]:=max;
  min[s]:=0;
  pre[s]:=s;
End;
Procedure FindPath;
Var
  count,u,v:integer;
  stop:boolean;
Begin
  count:=0;
  repeat
    stop:=true;
    count:=count+1;
    For u:=1 to n do
      For v:=1 to n do
        If (d[u,v]=0) and (min[u]+c[u,v]<min[v]) then
          begin
            min[v]:=min[u]+c[u,v];
            stop:=false;
            pre[v]:=u;
          end
        else If (d[v,u]=1) and (min[u]-c[u,v]<min[v]) then
          begin
            min[v]:=min[u]-c[u,v];
            stop:=false;
            pre[v]:=-u;
          end;
  until (count=n-1) or stop;
End;
Procedure TangLuong;
Var
  i,next:integer;
Begin
  i:=t;
  repeat
    next:=i;
    i:=pre[i];
    If i<0 then d[next,-i]:=0
    else d[i,next]:=1;
    i:=abs(i);
  until i=s;
End;
Procedure Solve;
Var
  count:integer;
  stop:boolean;
Begin
  count:=0;
  repeat
    stop:=true; inc(count);
    KhoiTri;
    FindPath;
    If min[t]<max then
      begin
        stop:=false;
        TangLuong;
      end;
  until (count=k) or stop;
  If stop then min[t]:=max;
End;
Procedure WriteOutput;
Var
  f:text;
  i,next,u,sl:integer;
  cost:longint;
  ds:array[1..maxn] of integer;
Begin
  Assign(f,fo); Rewrite(f);
  If min[t]=max then begin Writeln(f,-1); Close(f); exit; end;
  cost:=0;
  For i:=1 to n do
    For next:=1 to n do
      If d[i,next]=1 then
        cost:=cost+c[i,next];
  Writeln(f,cost);
  For i:=1 to k do
    begin
      u:=s; sl:=1; ds[sl]:=s;
      repeat
        inc(sl);
        For next:=1 to n do
        If d[u,next]=1 then
          begin
            d[u,next]:=0;
            ds[sl]:=next;
            break;
          end;
        u:=next;
      until u=t;
      Write(f,sl,' ');
      For u:=1 to sl do
        Write(f,ds[u],' ');
      Writeln(f);
    end;
  Close(f);
End;
BEGIN
  ReadInput;
  Solve;
  WriteOutput;
END.

Code mẫu của ll931110

program KWAY;
const
  input  = '';
  output = '';
  maxn = 102;
  maxt = 1000000;
var
  d,c,f: array[1..maxn,1..maxn] of longint;
  free: array[1..maxn,1..maxn] of boolean;

  trace,best: array[1..maxn] of longint;

  list: array[1..maxn] of longint;
  nl: longint;

  n,m,k,s,t: longint;
  count: longint;
  fi,fo: text;

  q: array[0..maxn] of longint;
  inqueue: array[1..maxn] of boolean;
  front,rear: longint;

procedure openfile;
begin
  assign(fi, input);  reset(fi);
  assign(fo, output);  rewrite(fo);
end;

procedure init;
var
  u,v,i: longint;
begin
  readln(fi, n, m, k, s, t);
  fillchar(c, sizeof(c), 0);
  fillchar(d, sizeof(d), 0);
  fillchar(f, sizeof(f), 0);

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

function FindPath: boolean;
var
  u,v: longint;
  nt,tmp: longint;
begin
  fillchar(trace, sizeof(trace), 0);
  fillchar(inqueue, sizeof(inqueue), false);
  for v := 1 to n do best[v] := maxt;
  best[s] := 0;

  front := 1;  rear := 1;  q[1] := s;
  nt := 1;
  repeat
    u := q[front];
    dec(nt);
    inqueue[u] := false;
    front := (front + 1) mod maxn;

    for v := 1 to n do
      if c[u,v] > f[u,v] then
        begin
          if f[u,v] = 0 then tmp := d[u,v] else tmp := d[u,v] * f[u,v] div abs(f[u,v]);
          if best[v] > best[u] + tmp then
            begin
              trace[v] := u;
              best[v] := best[u] + tmp;

              if not inqueue[v] then
                begin
                  inqueue[v] := true;
                  inc(nt);
                  rear := (rear + 1) mod maxn;
                  q[rear] := v;
                end;
            end;
        end;
  until nt = 0;

  FindPath := best[t] < maxt;
end;

procedure IncFlow;
var
  u,v: longint;
begin
  v := t;
  inc(count);
  while v <> s do
    begin
      u := trace[v];
      inc(f[u,v]);
      dec(f[v,u]);
      v := u;
    end;
end;

procedure solve;
begin
  count := 0;
  repeat
    if not FindPath then break;
    IncFlow;
  until count = k;
end;

procedure track(u: longint);
var
  v: longint;
begin
  inc(nl);  list[nl] := u;
  if u = t then exit;

  for v := 1 to n do
    if free[u,v] and (f[u,v] = 1) then
      begin
        free[u,v] := false;
        track(v);
        break;
      end;
end;

procedure printresult;
var
  i,j: longint;
  cost: longint;
begin
  if count < k then writeln(fo, -1) else
    begin
      fillchar(free, sizeof(free), true);
      cost := 0;
      for i := 1 to n do
        for j := 1 to n do
          if f[i,j] = 1 then cost := cost + d[i,j];

      writeln(fo, cost);
      for i := 1 to k do
        begin
          nl := 0;
          track(s);
          write(fo, nl, ' ');
          for j := 1 to nl do write(fo, list[j], ' ');
          writeln(fo);
        end;
    end;
end;

procedure closefile;
begin
  close(fo);
  close(fi);
end;

begin
  openfile;
  init;
  solve;
  printresult;
  closefile;
end.

Code mẫu của skyvn97

#include<bits/stdc++.h>
#define MAX   111
#define FOR(i,a,b) for (int i=(a);i<=(b);i=i+1)
#define REP(i,n) for (int i=0;i<(n);i=i+1)
#define FORE(i,v) for (__typeof((v).begin()) i=(v).begin();i!=(v).end();i++)
#define fi   first
#define se   second
using namespace std;
const int INF=(int)1e9+7;
typedef pair<int,int> ii;
void minimize(int &x,const int &y) {
    if (x>y) x=y;
}
class MaxFlowMinCost {
    public:
    struct edge {
        int from,to,capa,flow,cost;
        edge() {
            from=0;to=0;capa=0;flow=0;cost=0;
        }
        edge(int u,int v,int ca,int co) {
            from=u;to=v;capa=ca;flow=0;cost=co;
        }   
        int residual(void) const {
            return (capa-flow);
        }
    };
    vector<vector<int> > g;
    vector<edge> e;
    vector<int> d,tr;
    int n;
    MaxFlowMinCost() {
        n=0;
    }
    MaxFlowMinCost(int n) {
        this->n=n;
        g.assign(n+7,vector<int>());
        e.clear();
        d=vector<int>(n+7);
        tr=vector<int>(n+7);
    }
    void addedge(int u,int v,int ca,int co) {
        g[u].push_back(e.size());
        e.push_back(edge(u,v,ca,co));
        g[v].push_back(e.size());
        e.push_back(edge(v,u,0,-co));       
    }
    bool FordBellman(int s,int t) {
        FOR(i,1,n) {
            d[i]=INF;
            tr[i]=-1;
        }
        vector<bool> inq=vector<bool>(n+7,false);
        queue<int> q;
        while (!q.empty()) q.pop();
        q.push(s);inq[s]=true;d[s]=0;
        while (!q.empty()) {
            int u=q.front();q.pop();inq[u]=false;
            FORE(it,g[u]) if (e[*it].residual()>0) {
                int v=e[*it].to;
                if (d[v]>d[u]+e[*it].cost) {
                    d[v]=d[u]+e[*it].cost;
                    tr[v]=*it;
                    if (!inq[v]) {
                        q.push(v);
                        inq[v]=true;
                    }
                }
            }
        }
        return (d[t]<INF);
    }
    ii getflow(int s,int t) {
        int totflow=0;
        int totcost=0;
        while (FordBellman(s,t)) {
            int delta=INF;
            for (int u=t;u!=s;u=e[tr[u]].from) minimize(delta,e[tr[u]].residual());
            for (int u=t;u!=s;u=e[tr[u]].from) {
                e[tr[u]].flow+=delta;
                e[tr[u]^1].flow-=delta;
            }
            totflow+=delta;
            totcost+=delta*d[t];
        }
        return (ii(totflow,totcost));
    }
};
queue<int> q[MAX];
MaxFlowMinCost g;
int n,m,k,s,t;
void loadgraph(void) {
    scanf("%d",&n);
    scanf("%d",&m);
    scanf("%d",&k);
    scanf("%d",&s);
    scanf("%d",&t);
    g=MaxFlowMinCost(n+1);
    REP(i,m) {
        int u,v,c;
        scanf("%d",&u);
        scanf("%d",&v);
        scanf("%d",&c);
        g.addedge(u,v,1,c);
        g.addedge(v,u,1,c);
    }
    g.addedge(n+1,s,k,0);
}
void process(void) {
    ii res=g.getflow(n+1,t);
    if (res.fi<k) {
        printf("-1");
        return;
    }
    printf("%d\n",res.se);
    REP(i,g.e.size()) if (i%2==0 && g.e[i].flow>0 && g.e[i].from<=n) q[g.e[i].from].push(g.e[i].to);
    REP(zz,k) {
        vector<int> tmp;
        tmp.clear();
        int u=s;
        do {
            tmp.push_back(u);
            assert(!q[u].empty());
            int v=q[u].front();q[u].pop();
            u=v;
        }
        while (u!=t);
        tmp.push_back(t);
        printf("%d",tmp.size());
        FORE(it,tmp) printf(" %d",*it);
        printf("\n");
    }
}
int main(void) {
#ifndef ONLINE_JUDGE
    freopen("tmp.txt","r",stdin);
    printf("START\n");
#endif
    loadgraph();
    process();
    return 0;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.