最大流算法

  链接http://www.cnblogs.com/longdouhzt/archive/2012/05/20/2510753.html

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <map>
  7 #include <algorithm>
  8 #include <list>
  9 #include <ctime>
 10 #include <set>
 11 #include <string.h>
 12 #include <queue>
 13 using namespace std;
 14 
 15 int maxData = 0x3fffffff;
 16 
 17 int augment(int des, vector<int> pre, vector<vector<int> > path) {
 18     if (pre[des] == -1) //残留图中不再存在增广路径
 19         return -1;
 20     else {
 21         int res = maxData;
 22         int cur_des = des;
 23         int cur_pri = pre[des];
 24         while (cur_pri != -1) {
 25             res = min(res, path[cur_pri][cur_des]);
 26             cur_des = cur_pri;
 27             if (pre[cur_pri] == -1)
 28                 break;
 29             cur_pri = pre[cur_pri];
 30         }
 31         return res;
 32     }
 33 }
 34 int SPFA(int s, int des, vector<int> &pre, vector<vector<int> > path) {
 35     int n = path.size();
 36     queue<int> myqueue;
 37     int i;
 38     vector<int> d(n, -1);
 39     for (i = 0; i < n; ++i) { //初始化前驱
 40         pre[i] = -1;
 41     }
 42     for (i = 0; i < n; ++i) {
 43         d[i] = maxData; //将除源点以外的其余点的距离设置为无穷大
 44     }
 45     vector<bool> final(n, false); //记录顶点是否在队列中,SPFA算法可以入队列多次
 46     vector<int> cnt(n, 0); //记录顶点入队列次数
 47     d[s] = 0; //源点的距离为0
 48     final[s] = true;
 49     cnt[s]++; //源点的入队列次数增加
 50     myqueue.push(s);
 51     int topint;
 52     while (!myqueue.empty()) {
 53         topint = myqueue.front();
 54         myqueue.pop();
 55         final[topint] = false;
 56         for (i = 0; i < n; ++i) {
 57             if (d[topint] < maxData && d[i] > d[topint] + path[topint][i]
 58                     && path[topint][i] > 0) {
 59                 d[i] = d[topint] + path[topint][i];
 60                 pre[i] = topint;
 61                 if (!final[i]) { //判断是否在当前的队列中
 62                     final[i] = true;
 63                     cnt[i]++;
 64                     if (cnt[i] >= n) //当一个点入队的次数>=n时就证明出现了负环。
 65                         return true; //剩余网络中不会出现负数,且单位费用相当于1,这种算法更适合最小费用最大流
 66                     myqueue.push(i);
 67                 }
 68             }
 69         }
 70     }
 71     return augment(des, pre, path); //返回增广路径的值
 72 }
 73 
 74 int BFS(int src, int des, vector<int>& pre, vector<vector<int> > capacity) { //EK算法使用BFS寻找增广路径
 75     queue<int> myqueue;
 76     int i;
 77     int n = capacity.size(); //如果没错的话应该和pre的size一样
 78     vector<int> flow(n, 0); //标记从源点到当前节点实际还剩多少流量可用
 79     while (!myqueue.empty()) //队列清空
 80         myqueue.pop();
 81     for (i = 0; i < n; ++i) { //初始化前驱
 82         pre[i] = -1;
 83     }
 84     flow[src] = maxData; //初始化源点的流量为无穷大
 85     myqueue.push(src);
 86     while (!myqueue.empty()) {
 87         int index = myqueue.front();
 88         myqueue.pop();
 89         if (index == des) //找到了增广路径
 90             break;
 91         for (i = 0; i < n; ++i) { //遍历所有的结点
 92             if (i != src && capacity[index][i] > 0 && pre[i] == -1) {
 93                 pre[i] = index; //记录前驱
 94                 flow[i] = min(capacity[index][i], flow[index]); //关键:迭代的找到增量
 95                 myqueue.push(i);
 96             }
 97         }
 98     }
 99     if (pre[des] == -1) //残留图中不再存在增广路径
100         return -1;
101     else
102         return flow[des];
103 }
104 int maxFlow(int src, int des, vector<vector<int> > capacity) {
105 
106     int increasement = 0; //增广路径的值
107     int sumflow = 0; //最大流
108     int n = capacity.size();
109     vector<int> pre(n, -1); //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
110     while ((increasement = BFS(src, des, pre, capacity)) != -1) {
111         int k = des; //利用前驱寻找路径
112         while (k != src) {
113             int last = pre[k];
114             capacity[last][k] -= increasement; //改变正向边的容量
115             capacity[k][last] += increasement; //改变反向边的容量
116             k = last;
117         }
118         sumflow += increasement;
119     }
120     return sumflow;
121 }
122 
123 int main() {
124     vector<vector<int> > path(4, vector<int>(4, 0)); //记录残留网络的容量
125     vector<int> d(4, maxData);
126     for (int i = 0; i < 4; i++)
127         path[i][i] = maxData;
128     path[0][1] = path[1][0] = path[2][3] = 1;
129     path[1][2] = 5;
130     path[0][2] = 3;
131     path[1][3] = 2;
132     path[2][1] = 2;
133     path[0][3] = 3;
134     int sum = maxFlow(0, 3, path);
135     cout << sum;
136     return 0;
137 }
原文地址:https://www.cnblogs.com/kakamilan/p/2634072.html