ec1117

dinic

Dec 31st, 2020 (edited)
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.99 KB | None | 0 0
  1. /**
  2.  * Description: Fast flow. After computing flow, edges $\{u,v\}$ such that
  3.     * $lev[u] \neq -1,$ $lev[v] = -1$ are part of min cut.
  4.     * Use \texttt{reset} and \texttt{rcap} for Gomory-Hu.
  5.  * Time: $O(N^2M)$ flow, $O(M\sqrt N)$ bipartite matching
  6.  * Source: GeeksForGeeks, Chilli
  7.  * Verification: RMI 2017 Day 1 Fashion
  8.     * https://pastebin.com/VJxTvEg1
  9.  */
  10.  
  11. template<int SZ> struct Dinic {
  12.     int N,s,t; // # verts, source, sink
  13.     typedef ll F; // flow type
  14.     struct Edge { int to, rev; F flo, cap; };
  15.     vector<Edge> adj[SZ]; // use asserts, don't be dumb
  16.     void reset() { F0R(i,N) trav(e,adj[i]) e.flo = 0; }
  17.     void ae(int u, int v, F cap, F rcap = 0) {
  18.         assert(min(cap,rcap) >= 0);
  19.         Edge a{v,sz(adj[v]),0,cap}, b{u,sz(adj[u]),0,rcap};
  20.         adj[u].pb(a), adj[v].pb(b); }
  21.     int lev[SZ]; typename vector<Edge>::iterator cur[SZ];
  22.     bool bfs() { // level = shortest distance from source
  23.         F0R(i,N) lev[i] = -1, cur[i] = begin(adj[i]);
  24.         queue<int> q({s}); lev[s] = 0;
  25.         while (sz(q)) {
  26.             int u = q.ft; q.pop();
  27.             trav(e,adj[u]) if (lev[e.to] < 0 && e.flo < e.cap)
  28.                 q.push(e.to), lev[e.to] = lev[u]+1;
  29.         }
  30.         return lev[t] >= 0;
  31.     }
  32.     F dfs(int v, F flo) {
  33.         if (v == t) return flo;
  34.         for (; cur[v] != end(adj[v]); cur[v]++) {
  35.             Edge& e = *cur[v];
  36.             if (lev[e.to]!=lev[v]+1||e.flo==e.cap) continue;
  37.             F df = dfs(e.to,min(flo,e.cap-e.flo));
  38.             if (df) { e.flo += df; adj[e.to][e.rev].flo -= df;
  39.                 return df; } // saturated >=1 one edge
  40.         }
  41.         return 0;
  42.     }
  43.     F maxFlow(int _N, int _s, int _t) {
  44.         N = _N, s = _s, t = _t; assert(s != t);
  45.         F tot = 0; while (bfs()) while (F df =
  46.             dfs(s,numeric_limits<F>::max())) tot += df;
  47.         return tot;
  48.     }
  49. };
  50.  
  51. //petya
  52. const int MX = 2500;
  53. const int S = 0;
  54. const int T = MX - 1;
  55. const int INF = 2e9;
  56.  
  57. vector<pair<int, int>> edge;
  58. vector<int> adj[MX];
  59. bool vstd[MX];
  60. ll ans;
  61.  
  62. void addEdge(int u, int v, int w) {
  63.     adj[u].push_back(edge.size());
  64.     edge.emplace_back(v, w);
  65.     adj[v].push_back(edge.size());
  66.     edge.emplace_back(u, 0);
  67. }
  68.  
  69. bool dfs(int u, int thr) {
  70.     if (u == T) {
  71.         ans -= thr;
  72.         return true;
  73.     }
  74.     vstd[u] = true;
  75.     for (auto e : adj[u]) {
  76.         auto& [v, w] = edge[e];
  77.         if (w < thr || vstd[v])
  78.             continue;
  79.         if (dfs(v, thr)) {
  80.             w -= thr;
  81.             edge[e ^ 1].second += thr;
  82.             return true;
  83.         }
  84.     }
  85.     return false;
  86. }
  87.  
  88. int main() {
  89.     ios_base::sync_with_stdio(0);
  90.     cin.tie(0);
  91.  
  92.     int n, m;
  93.     cin >> n >> m;
  94.     for (int i = 1; i <= n; ++i) {
  95.         int a;
  96.         cin >> a;
  97.         addEdge(i, T, a);
  98.     }
  99.     for (int i = n + 1; i <= n + m; ++i) {
  100.         int u, v, w;
  101.         cin >> u >> v >> w;
  102.         ans += w;
  103.         addEdge(S, i, w);
  104.         addEdge(i, u, INF);
  105.         addEdge(i, v, INF);
  106.     }
  107.  
  108.     for (int i = INF; i; i /= 2) {
  109.         while (true) {
  110.             memset(vstd, false, sizeof vstd);
  111.             if (!dfs(S, i))
  112.                 break;
  113.         }
  114.     }
  115.     cout << ans << '\n';
  116. }
  117.  
Add Comment
Please, Sign In to add comment