• [SDOI2009]晨跑[最小费用最大流]


    [SDOI2009]晨跑

    最小费用最大流的板子题吧

    (i'=i+n)
    (i -> i') 建一条流量为1费用为0的边这样就不会对答案有贡献
    其次是对 (m) 条边建 (u'->v) 流量为1费用为cost反向为0费用为-cost (单向边,不管

    这样建图就有从必须令 (1')为源点 (n) 为汇点
    然后每条流的路线都是 (1' -> u_1 -> u_1' -> u_2 -> u_2' -> ... -> n)
    于是就可以直接MCMF板子……

    #include <bits/stdc++.h>
    using namespace std ;
    using ll = long long ;
    using pii = pair < int , int > ;
    void read(int & x) {
      char c = x = 0 ; bool f = 1 ;
      while(c < '0' || c > '9') { if(c == '-') f = 0 ; c = getchar() ; }
      while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
      x = f ? x : -x ;
    }
    int n , m , s , t ;
    const int N = 5e3 + 10 ;
    const int M = 5e4 + 10 ;
    namespace MCMF {
      void cmax(int & x , int y) { if(x < y) x = y ; }
      void cmin(int & x , int y) { if(x > y) x = y ; }
      struct Edge { int v , nxt , f , c ; } e[M << 1] ;
      int cnt = 1 , head[N] , pre[N] , dis[N] , vis[N] ;
      void add(int u , int v , int flow , int cost) {
        e[++ cnt] = { v , head[u] , flow , cost } ; head[u] = cnt ;
        e[++ cnt] = { u , head[v] , 0 , -cost } ; head[v] = cnt ;
      }
      bool spfa(int s) {
        memset(dis , 0x3f , sizeof(dis)) ;
        queue < int > q ; dis[s] = 0 ; q.push(s) ;
        while(q.size()) {
          int u = q.front() ; q.pop() ; vis[u] = 0 ;
          for(int i = head[u] ; i ; i = e[i].nxt) {
            int v = e[i].v ;
            if(dis[v] > dis[u] + e[i].c && e[i].f) {
              dis[v] = dis[u] + e[i].c ; pre[v] = i ;
              if(! vis[v]) { vis[v] = 1 ; q.push(v) ; }
            }
          }
        }
        return (dis[t] ^ dis[0]) ;
      }
      int upd(int & maxflow) {
        int p = 0 , mn = 1e9 , cost = 0 ;
        for(int u = t ; u ^ s ; u = e[p ^ 1].v) cmin(mn , e[p = pre[u]].f) ;
        for(int u = t ; u ^ s ; u = e[p ^ 1].v) { e[p = pre[u]].f -= mn ; e[p ^ 1].f += mn ; cost += e[p].c * mn ; }
        return maxflow += mn , cost ;
      }
      void EK(int & maxflow , int & mincost) { while(spfa(s)) mincost += upd(maxflow) ; }
    }
    using namespace MCMF ;
    signed main() {
      read(n) ; read(m) ; s = n + 1 ; t = n ;
      for(int i = 1 ; i <= m ; i ++) { int u , v , flow = 1 , cost ; read(u) ; read(v) ; read(cost) ; add(u + n , v , flow , cost) ; }
      for(int i = 1 ; i <= n ; i ++) { add(i , i + n , 1 , 0) ; }
      int maxflow = 0 , mincost = 0 ;
      EK(maxflow , mincost) ;
      printf("%d %d
    " , maxflow , mincost) ;
      return 0 ;
    }
    
  • 相关阅读:
    HDU 4460 Friend Chains 第37届ACM/ICPC杭州赛区题目 (bfs求最短路,求两两之间最短路的最大值)
    HDU 4445 Crazy Tank (简单物理题,枚举)
    HDU 4433 locker 第37届ACM/ICPC 天津赛区现场赛C题(DP)
    JQuery 3级级联,3级联动,3级连动
    C++异常处理
    C++ Template
    学会用core dump调试程序错误(转)
    C++命名规则
    vim实用配置(转)
    GDB多进程调试(转)
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11997189.html
Copyright © 2020-2023  润新知