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 };