开始编程前分析设计思路和程序的整体的框架,以及作为数学问题的性质:
程序流程图:
数学原理:
基于Bellman-Ford算法的最小费用最大流,通过不断松弛图中的边来更新节点之间的最短距离,除了考虑边的容量和费用外,还需要考虑流量的限制,对所有边进行松弛操作。在重复地计算中,已计算得到正确的距离的边的数量不断增加,直到所有边都计算得到了正确的路径。
时间复杂度分析:
在Bellman-Ford算法中,外层循环执行了n次,其中n是节点的数量。对于每个节点,内层循环会遍历该节点的所有邻接边,假设每个节点的平均度数为d,则内层循环最多执行d次。总的时间复杂度为O(n * d),即O(n^2)
源代码:
#include <iostream> #include <queue> #include <vector> #include <algorithm> #include <cstring> using namespace std; #define N 1010 typedef struct edge { int from; // 起点 int to; // 终点 int cap; // 容量 int flow; // 流量 int cost; // 费用 }Edge; //用于存储每个节点的最短距离 //用于存储每个节点的前驱节点 //用于存储每个节点到起点的距离 //用于标记每个节点是否在队列中 int a[N], p[N], d[N], inq[N]; vector<Edge> edges; //用于存储每个节点的邻接表(边的编号) vector<int> G[N]; int n, m, s, t, T; int fflow = 0, total_cost = 0; bool Bellman_Ford(int s, int t) { memset(a, 0, sizeof(a)); memset(p, 0, sizeof(p)); memset(inq, 0, sizeof(inq)); for (int i = 1; i <= n; i++) { d[i] = 1000000; } a[s] = 10000; d[s] = 0; queue<int> Q; Q.push(s); p[s] = 0; inq[s] = 1; while (!Q.empty()) { int x = Q.front(); Q.pop(); inq[x] = 0; for (int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; //若该点能够被松弛,下面更新a,p,d,并判断该点能否入队 if (e.cap > e.flow && d[e.to] > d[x] + e.cost) { d[e.to] = d[x] + e.cost; p[e.to] = G[x][i]; a[e.to] = min(a[x], e.cap - e.flow); if (inq[e.to] == 0) { Q.push(e.to); inq[e.to] = 1; } } } } //Bellman_Ford在当前残量图中松弛完毕后,下面更新其所涉及边的流量变化。 //首先查看d[t]是否发生了变化,若不变,则说明已无增广路 if (d[t] == 1000000) { return false; } else//若d[t]的值得到更新,则考虑更新残量图 { fflow += a[t]; total_cost += d[t] * a[t]; for (int i = t; i != s; i = edges[p[i]].from) { edges[p[i]].flow += a[t]; edges[p[i]^1].flow -= a[t]; } return true; } } int main() { int a, b, c, co; cout << "总顶点 边数 源点 汇点" << endl; cin >> n >> m >> s >> t; cout << "前 后 容量 费用" << endl; for (int i = 1; i <= m; i++) { cin >> a >> b >> c >> co; Edge e; e.from = a; e.to = b; e.cap = c; e.cost = co; e.flow = 0; edges.push_back(e); e.from = b; e.to = a; e.cap = 0; e.cost = -co; e.flow = 0; edges.push_back(e); int num = edges.size(); G[a].push_back(num - 2); G[b].push_back(num - 1); } while (Bellman_Ford(s, t)); cout << "流量:" << fflow << endl; cout << "总费用:" <<total_cost << endl; system("pause"); return 0; }
测试用例:(图结构)
输出结果: