HDUOJ3549
来源:互联网 发布:淘宝网旅游帐篷 编辑:程序博客网 时间:2024/06/07 02:14
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3549
题目大意:
有向图求最大流
解题过程:
关于为什么增加流量时要增加一个反向负流量的边纠结了很久,最后还是想通了,其他就没难点了。
题目分析:
增广路算法,每一次尽可能的添加一条增广路,直到不能添加增广路为止,不过有个特殊的地方,按照挑战书上的说法是,可以把之前的流推回去。按照我的理解大概是现在的这个新加的增广路用之前流量的路径,然后把之前流的路径推回去,然后之前的流量寻找一个新的路径。
AC代码:
#include <bits/stdc++.h>using namespace std;const int MAX = 20, INF = 0x3f3f3f3f;struct Node { //to表示要指向的点,cap是剩余流量,rev是指这条边的方向边是to这个点的第几条边 int to, rev, cap; Node(int to, int cap, int rev):to(to), cap(cap), rev(rev) {}};vector<Node> edge[MAX];int vis[MAX];void add_edge(int u, int v, int w) { //添加边和反向边 edge[u].push_back(Node(v, w, edge[v].size())); edge[v].push_back(Node(u, 0, edge[u].size()-1));}int dfs(int u, int end, int f) { if (u == end) return f; vis[u] = 1; for (int i = 0; i < edge[u].size(); i++) { Node& e = edge[u][i]; if (!vis[e.to] && e.cap > 0) { int d = dfs(e.to, end, min(f, e.cap)); //如果找到了增广路就返回 if (d > 0) { //正向边容量减少的时候,反向边要增加容量 e.cap -= d; edge[e.to][e.rev].cap += d; return d; } } } return 0;}int max_flow(int s, int t) { int flow = 0; for (;;) { memset(vis, 0, sizeof(vis)); int f = dfs(s, t, INF); //如果找不到增广路了,那么当前就是最大流了,返回 if (f == 0) return flow; flow += f; }}int main() { int T; scanf("%d", &T); for (int cases = 1; cases <= T; cases++) { int n, m; scanf("%d %d", &n, &m); for (int i = 0; i <= n; i++) edge[i].clear(); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d %d %d", &u, &v, &w); add_edge(u, v, w); } printf("Case %d: %d\n", cases, max_flow(1, n)); }}