最小费用最大流(SPFA版本)

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  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\n", 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 }

 

你可能感兴趣的:(最小费用最大流(SPFA版本))