HDU1532 Drainage Ditches
最大流算法(EdmondsKarp)
参考了这篇文章(EdmondsKarp)的对EK最大流算法的解释。
对于这个有向有环图,可以创建它的残量网络,即该图的每一条路径的值为当前从一点到另一点可以增加的流量的值。一条路径流量被用了多少,就说明可以有多少流量可以通过其反向路径。创建以后通过dfs找出从起点到终点的最短路径并更新路径的流量,返回该路径的流量。流量为0就代表没有从起点到终点的路径。
对于该题目,因为有环,所以还需要一个数组来标记某节点是否经过以避免无限循环。
具体的一些细节:
每个节点有一个路径数组。
路径类(struct node)有三个属性:to,val,rev。to是该路径指向的节点,val是该路径的流量,rev是该路径指向的节点的路径数组中指向本节点的路径的编号。(用于更新路径的逆路径)
AC代码如下:
#include<iostream> #include<cstdio> #include<vector> using namespace std; struct node { int to, val,rev;//去到的节点;剩余容量;nodeNet[to].rev为自身的数组编号 node(int to, int val, int rev) :to(to), val(val), rev(rev) {} }; int min(int a, int b) { return a < b ? a : b; } int N, M; vector<node> nodeNet[205]; vector<bool> passed(205,false); //深度优先算法求当前最短路径,返回最短路径的流量 int dfs(int from,int to,int v) { if (from == to)return v; passed[from] = true; for (int i = 0; i < nodeNet[from].size(); ++i) { node& tmp = nodeNet[from][i]; if (!passed[tmp.to]&&tmp.val>0) { int d = dfs(tmp.to, to, min(v, tmp.val)); if (d > 0) { tmp.val -= d; nodeNet[tmp.to][tmp.rev].val += d; return d; } } } return 0; } void addNode(int from,int to,int val) { nodeNet[from].push_back(node(to,val,nodeNet[to].size())); nodeNet[to].push_back(node(from, 0,nodeNet[from].size()-1)); } int getResult(int from, int to) { int res = 0; while (true) { for (int i = 0; i < passed.size(); ++i) passed[i] = false; int d = dfs(from, to, 10000000); if (d > 0)res += d; else return res; } } int main() { while (scanf("%d%d", &N, &M) == 2) { for (int i = 0; i <= N; ++i) nodeNet[i].clear(); for (int i = 0; i < N; ++i) { int x, y,rate; scanf("%d%d%d", &x, &y,&rate); addNode(x, y, rate); } printf("%d\n", getResult(1, M)); } }
(本垃圾对dfs还是理解的不够深啊)