zoukankan      html  css  js  c++  java
  • 最小费用最大流(SPFA版本)

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <queue>
      5 
      6 using namespace std;
      7 
      8 #define LL long long
      9 #define pb push_back
     10 #define fi first
     11 #define se second
     12 
     13 
     14 //时间复杂度: O(V * E^2 * log(V))
     15 //SPFA中不会出现负环,如果出现环,则说明这些边还有流量,
     16 //但是每次流过之后这些边的流量都会减去,加上反向边
     17 
     18 
     19 const int N = 5e3 + 10;
     20 const int M = 5e4 + 10;
     21 const int INF = 1e9;
     22 
     23 struct edge{
     24     int to, nxt, cap ,flow, cost;
     25 }e[M << 2];
     26 int head[N], vis[N], dis[N], pre[N];
     27 queue<int > que;
     28 int n, m, s, t, tot;
     29 
     30 inline void add(int u, int v, int cap, int w){
     31     e[tot].to = v; e[tot].cap = cap; e[tot].cost = w;
     32     e[tot].flow = 0; e[tot].nxt = head[u]; head[u] = tot++;
     33     e[tot].to = u; e[tot].cap = 0; e[tot].cost = -w;
     34     e[tot].flow = 0; e[tot].nxt = head[v]; head[v] = tot++;
     35 }
     36 
     37 void init(){
     38     for(int i = 0; i <= n; ++i){
     39         dis[i] = INF;
     40         vis[i] = 0;
     41         pre[i] = -1;
     42     }
     43     while(!que.empty()) que.pop();
     44 }
     45 
     46 bool SPFA(){
     47     init();
     48     dis[s] = 0;
     49     vis[s] = 1;
     50     que.push(s);
     51 
     52     int now, to, cap, flow, cost;
     53     while(!que.empty()){
     54         now = que.front();
     55         que.pop();
     56         vis[now] = 0;
     57 
     58         for(int o = head[now]; ~o; o = e[o].nxt){
     59             to = e[o].to;
     60             cap =  e[o].cap;
     61             flow = e[o].flow;
     62             cost = e[o].cost;
     63 
     64             if(cap - flow > 0 && dis[to] > dis[now] + cost){
     65                 dis[to] = dis[now] + cost;
     66 
     67                 //记录来源
     68                 pre[to] = o;
     69 
     70                 if(!vis[to]){
     71                     vis[to] = 1;
     72                     que.push(to);
     73                 }
     74             }
     75         }    
     76     }
     77 
     78     if(pre[t] == -1) return false;
     79     else return true;
     80 }
     81 
     82 void mcmf(){
     83     
     84     int mf = 0, mc = 0;    
     85     while(SPFA()){
     86         int Min = INF;
     87 
     88         //找到最窄的水管
     89         for(int o = pre[t]; ~o; o = pre[e[o ^ 1].to]){
     90             Min = min(Min, e[o].cap - e[o].flow);
     91         }
     92 
     93         //更新流量
     94         for(int o = pre[t]; ~o; o = pre[e[o ^ 1].to]){
     95             e[o].flow += Min;
     96             e[o ^ 1].flow -= Min;
     97         }
     98         mf += Min;
     99         mc += Min * dis[t];
    100     }
    101 
    102     printf("%d %d
    ", mf, mc);
    103 }
    104 
    105 void solve(){
    106     scanf("%d%d%d%d", &n, &m, &s, &t);
    107     for(int i = 0; i <= n; ++i) head[i] = -1; tot = 0;
    108     
    109     int u, v, w, f;
    110     for(int i = 0; i < m; ++i){
    111         scanf("%d%d%d%d", &u, &v, &w, &f);
    112         add(u, v, w, f);
    113     }
    114     mcmf();
    115 }
    116 
    117 int main(){
    118 
    119     solve();
    120 
    121     return 0;
    122 }
  • 相关阅读:
    SNMP监控一些常用OID表的总结
    微信公众号开发(三)----服务号客服消息
    微信公众号开发(二)---验证服务与回复消息
    微信公众号开发(一)-----准备工作
    leveldb文章列表
    TinyIM流程之删除好友
    TinyIM流程之添加好友
    《软件创富----共享软件创业之道》读后感
    TinyIM流程之用户注销
    TinyIM流程之用户退出登录
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/13149800.html
Copyright © 2011-2022 走看看