Hướng dẫn giải của Trao đổi thông tin


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

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;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.