hdu 2549 Flow Problem 最大流
//hdu 2549 Flow Problem 最大流 //简单最大流 //EK算法居然比 同时找多条增广路的dinic算法还快 // //dinic要注意找不到增广路的点的层次要标为-1 // //具体看代码 #include <iostream> #include <stdio.h> #include <string.h> #include <queue> using namespace std; #define INF (1<<30) #define N 25 int map[N][N], fa[N]; bool vis[N]; bool bfs(int n) { memset(vis, false, sizeof(vis)); memset(fa, -1, sizeof(fa)); queue<int>que; que.push(1); vis[1] = true; while(!que.empty()) //广搜找增广路 { int now = que.front(); que.pop(); vis[now] = true; for(int i = 1; i <= n; ++i) { if(vis[i] == false && map[now][i] > 0) { vis[i] = true; fa[i] = now; if(i == n) return true; que.push(i); } } } return false; } void EK(int n, int m) { int ans = 0; while(bfs(n)) //找增广路 { int min = INF;//找增广路的瓶颈,也就是找到这条增广路 for(int i = n; i != 1; i = fa[i]) //留向汇点的流量 min = map[fa[i]][i] < min ? map[fa[i]][i] : min; for(int i = n; i != 1; i = fa[i]) { map[fa[i]][i] -= min; map[i][fa[i]] += min; //建反向边 } ans += min; } printf("%d\n", ans); } int main() { int n_case; scanf("%d", &n_case); for(int j = 1; j <= n_case; ++j) { printf("Case %d: ", j); int n, m; scanf("%d%d", &n, &m); memset(map, 0, sizeof(map)); for(int i = 0; i < m; ++i) { int from, to, f; scanf("%d%d%d", &from, &to, &f); map[from][to] += f; } EK(n, m); } return 0; }
dinic
#define comein freopen("in.txt", "r", stdin); #include <stdio.h> #include <string.h> #include <queue> #include <algorithm> using namespace std; #define INF 1<<30 #define N 2000 int eid; int head[N], to[N], cap[N], next[N]; int level[N]; void add_edge(int from, int t, int f) { to[eid] = t; cap[eid] = f; next[eid] = head[from]; head[from] = eid++; to[eid] = from; //建反向边 cap[eid] = 0; next[eid] = head[t]; head[t] = eid++; } bool bfs(int root, int n_point) //残余网络分层 { memset(level, -1, sizeof(level)); queue<int>que; que.push(root); level[root] = 0; while(!que.empty()) { root = que.front(); que.pop(); for(int i = head[root]; i != -1; i = next[i]) { //边还有残余容量,且下一个点还没分层 if(level[to[i]] == -1 && cap[i]) { level[to[i]] = level[root] + 1; if(to[i] == n_point) return true; que.push(to[i]); } } } return false; } int dfs(int root, int f, int n_point) { if(root == n_point) return f; int flow, ans = 0; for(int i = head[root]; i != -1; i = next[i]) { int m = min(cap[i], f - ans); if(cap[i] && level[root]+1 == level[to[i]] && (flow = dfs(to[i], m, n_point ) ) ) { //下标从0开始,则正向边为偶数,反向边为基数; cap[i] -= flow; cap[i^1] += flow;//下标从1开始则不能用 异或 ans += flow; } } if(ans == 0) //若没找到增广路,这时注意要把该点 level[root] = -1; //的层次标为-1,表示不能到达 return ans; } void dinic(int n_point) { int flow = 0; while(bfs(1, n_point)) //分层 { while(1) //每条增广路都有一个瓶颈(增光路上最小容量的边) { //每次分层都要把所有增广路的瓶颈都清除掉,再重新分层 int f = dfs(1, INF, n_point);//因此最多层分v次 if(f == 0) break; flow += f; } } printf("%d\n", flow); } int main() { eid = 0; int n_case; scanf("%d", &n_case); for(int t = 1; t <= n_case; ++t) { printf("Case %d: ", t); int n_point, n_edge; scanf("%d%d", &n_point, &n_edge); memset(head, -1, sizeof(head)); while(n_edge--) { int from, to, f; scanf("%d%d%d", &from, &to, &f); add_edge(from, to, f); } dinic(n_point); } return 0; }