最小费用最大流 模板

 1 struct Edge{
 2     int from, to, cap, flow, cost;//出点,入点,容量,当前流量,费用(也就是权值)
 3     Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {}
 4 };
 5 
 6 struct MCMF
 7 {
 8     int n, m;
 9     vector<Edge> edges;//保存表
10     vector<int> G[MAXN];//保存邻接关系
11     int inq[MAXN];//判断一个点是否在队列当中(SPFA算法当中要用)
12     int d[MAXN];//起点到d[i]的最短路径保存值
13     int p[MAXN];//用来记录路径,保存上一条弧
14     int a[MAXN];//找到增广路径后的改进量
15 
16     void init(int n)//初始化
17     {
18         this->n = n;
19         for (int i = 0; i <= n; i++)
20             G[i].clear();
21         edges.clear();
22     }
23   
24     void AddEdge(int from, int to, int cap, int cost)//添加有向边
25     {
26         edges.push_back(Edge(from, to, cap, 0, cost));//正向
27         edges.push_back(Edge(to, from, 0, 0, -cost));//反向
28         m = edges.size();
29         G[from].push_back(m - 2);//按照边的编号保存邻接关系
30         G[to].push_back(m - 1);
31     }
32 
33     bool BellmanFord(int s, int t, int& flow, long long& cost)//最短路径算法
34     {
35         for (int i = 0; i <= n; i++)
36             d[i] = INT_MAX;
37         memset(inq, 0, sizeof(inq));
38         d[s] = 0;
39         inq[s] = 1;
40         p[s] = 0;
41         a[s] = INT_MAX;
42 
43         queue<int> Q;
44         Q.push(s);
45         while (!Q.empty())
46         {
47             int u = Q.front();
48             Q.pop();
49             inq[u] = 0;
50             for (int i = 0; i < G[u].size(); i++)
51             {
52                 Edge& e = edges[G[u][i]];
53                 if (e.cap > e.flow&&d[e.to] > d[u] + e.cost)//寻找满足容量大于流量的可松弛边
54                 {
55                     d[e.to] = d[u] + e.cost;
56                     p[e.to] = G[u][i];
57                     a[e.to] = min(a[u], e.cap - e.flow);
58                     if (!inq[e.to])//是否在队列当中
59                     {
60                         Q.push(e.to);
61                         inq[e.to] = 1;
62                     }
63                 }
64             }
65         }
66         if (d[t] == INT_MAX)//如果d[t]没有被更新,相当于没找到增广路径,则没有最大流也没有最小费用
67             return false;
68         flow += a[t];//更新最大流
69         cost += (long long)d[t] * (long long)a[t];//单位流量乘以单位路径长度用来计算消耗
70         for (int u = t; u != s; u = edges[p[u]].from)//通过使用p[]保存的上一个边的值来对刚刚找到的增广路径上面的流量进行更新
71         {
72             edges[p[u]].flow += a[t];//正向变更新
73             edges[p[u] ^ 1].flow -= a[t];//反向变更新(用位运算实现的)
74         }
75         return true;
76     }
77 
78     int MincostMaxflow(int s, int t, long long& cost)//计算从s到t的最小消耗cost,返回最大流
79     {
80         int flow = 0;
81         cost = 0;
82         while (BellmanFord(s, t, flow, cost));//不断寻找最短增广路径,直到找不到为止
83         return flow;
84     }
85 };

 


 

固定流量的最小消费

 1 struct Edge {
 2     int from, to, cap, flow, cost;
 3     Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {}
 4 };
 5 
 6 struct MCF {
 7     int n, m;
 8     vector<Edge> edges;
 9     vector<int> G[MAXN];
10     int inq[MAXN];         // 是否在队列中
11     int d[MAXN];           // Bellman-Ford
12     int p[MAXN];           // 上一条弧
13     int a[MAXN];           // 可改进量
14     void init(int n) {
15         this->n = n;
16         for (int i = 0; i < n; i++) G[i].clear();
17         edges.clear();
18     }
19     void AddEdge(int from, int to, int cap, int cost) {
20         edges.push_back(Edge(from, to, cap, 0, cost));
21         edges.push_back(Edge(to, from, 0, 0, -cost));
22         m = edges.size();
23         G[from].push_back(m - 2);
24         G[to].push_back(m - 1);
25     }
26     bool BellmanFord(int s, int t, int flow_limit, int& flow, int& cost) {
27         for (int i = 0; i < n; i++) d[i] = INF;
28         memset(inq, 0, sizeof(inq));
29         d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
30 
31         queue<int> Q;
32         Q.push(s);
33         while (!Q.empty()) {
34             int u = Q.front(); Q.pop();
35             inq[u] = 0;
36             for (int i = 0; i < G[u].size(); i++) {
37                 Edge& e = edges[G[u][i]];
38                 if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
39                     d[e.to] = d[u] + e.cost;
40                     p[e.to] = G[u][i];
41                     a[e.to] = min(a[u], e.cap - e.flow);
42                     if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
43                 }
44             }
45         }
46         if (d[t] == INF) return false;
47         if (flow + a[t] > flow_limit) a[t] = flow_limit - flow;
48         flow += a[t];
49         cost += d[t] * a[t];
50         for (int u = t; u != s; u = edges[p[u]].from) {
51             edges[p[u]].flow += a[t];
52             edges[p[u] ^ 1].flow -= a[t];
53         }
54         return true;
55     }
56     // 最小费用流(流量确定)
57     // 需要保证初始网络中没有负权圈
58     int MincostFlow(int s, int t, int flow_limit, int& cost) {
59         int flow = 0; cost = 0;
60         while (flow < flow_limit && BellmanFord(s, t, flow_limit, flow, cost));
61         return flow;
62     }
63 };

 

posted @ 2018-08-31 18:39  romaLzhih  阅读(275)  评论(0编辑  收藏  举报