poj1273 经典的网络流例子
这里结网络流使用的是dinic 算法
相比于EdmondsKarp算法
每次bfs一次才可以找到一条增广路径的效率太低了
dinic算法 先使用bfs对图进行分层
分完层后 不断的进行dfs 搜索增广路径
直到图中不可以dfs的栈为空后 再进行重新分分层
然后再不断的进行dfs搜索增广路径
直到bfs不能再到达汇点 返回最大流
include <iostream>
#include <deque>
using namespace std;
const int INF = 0xfffffff;
const int MAXSIZE = 201;
int G[MAXSIZE][MAXSIZE];
int layer[MAXSIZE];//存储bfs的层次信息
int visit[MAXSIZE];//在dfs中存储访问信息 用来回溯
int n, m;//n为边的个数 m为点的个数
bool bfs()
{
deque<int> q;
q.push_back(1);
memset(layer, -1, sizeof(layer));//把所有没有访问过的点的层数设置为-1 作为没有访问的标识
layer[1] = 0;
while (!q.empty())
{
int temp = q.front();
q.pop_front();
for (int i = 1; i <= m; i++)
{
if (layer[i] == -1 && G[temp][i] > 0)//i没有被访问过且 temp到I有路径
{
layer[i] = layer[temp] + 1;
q.push_back(i);
if (i == m)//bfs从第源点找到了汇点
return true;
}
}
}
return false;//从源点的bfs没有找到汇点
}
int dinic()
{
int sum = 0;//存储最大流量
deque<int> q;
while (bfs())
{
memset(visit, 0, sizeof(visit));//清空visit数组
q.push_back(1);
visit[1] = 1;
while (!q.empty())
{
int temp = q.back();
if (temp == m)//找到了汇点
{
int min = INF;//增广路径中的增量
int mins;//增量的起点
for (int i = 1; i < q.size(); i++)//寻找增量
{
int u = q[i - 1];
int v = q[i];
if (G[u][v] < min)
{
min = G[u][v];
mins = u;
}
}
sum += min;//增加总的流量
for (int i = 1; i < q.size(); i++)//更新网络
{
int u = q[i - 1];
int v = q[i];
G[u][v] -= min;
G[v][u] += min;
}
for (int a = q.back(); (!q.empty()) && (a != mins); q.pop_back())//回溯到增量的起点 寻找下条增广路径
visit[a] = 0;
}
else//没有找到汇点
{
int i;
for (i = 1; i <= m; i++)
{
if (!visit[i] && G[temp][i]>0 && layer[i] == layer[temp] + 1)
{
q.push_back(i);
visit[i] = 1;
break;
}
}
if (i > m)//根据当前的dfs没有找到汇点 且访问完了所有节点 则回溯
q.pop_back();
}
}
}
return sum;
}
int main()
{
while (cin >> n >> m)//n为边数 m为点的个数
{
memset(G, 0, sizeof(G));
int u, v, w;
for (int i = 0; i < n; i++)
{
cin >> u >> v >> w;
G[u][v] += w;
}
cout << dinic() << endl;
}
return 0;
}