[POJ1273]Drainage Ditches 网络流(最大流)
2015-11-13 11:31
411 查看
题目链接:http://poj.org/problem?id=1273
网络流裸题,注意有重边。重边的处理方法很简单,就是将对应的c叠加到对应边上。注意初始化为0。
我用的是最朴素的FF方法,即找增广路。之前用dfs找增广路WA了,应该是碰到了随机找一条增光路这种方法碰到了killer case。给出WA代码(初学用喜闻乐见链式前向星建图,比较繁琐。不过好在最终还是WA掉了)。
随后索性全部删掉一切从简,改用最简单的邻接矩阵。利用BFS,第一次接触到汇点的那条路径一定是最短的(因为BFS是层进的)。找到了这条路并且记录下来即可。
接着,从源向外发出一个流(一定要足够大),按照之前BFS到的最短增广路流向汇点,根据短板效应找到流量,更新到最大流量上之后再更新残余网络(直接在原网络上更新即可)。下图可以比较清晰地说明这一点:
Dinic
网络流裸题,注意有重边。重边的处理方法很简单,就是将对应的c叠加到对应边上。注意初始化为0。
我用的是最朴素的FF方法,即找增广路。之前用dfs找增广路WA了,应该是碰到了随机找一条增光路这种方法碰到了killer case。给出WA代码(初学用喜闻乐见链式前向星建图,比较繁琐。不过好在最终还是WA掉了)。
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; typedef struct Edge { int v; int c; int next; Edge() { next = -1; } }Edge; const int maxn = 222; int n, m, s, t; int head[maxn]; int vis[maxn]; int cnt = 0; Edge edge[maxn<<1]; void init() { memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); cnt = 0; } void adde(int u, int v, int c) { edge[cnt].v = v; edge[cnt].next = head[u]; edge[cnt].c = c; head[u] = cnt++; edge[cnt].v = v; edge[cnt].next = head[u]; edge[cnt].c = 0; head[v] = cnt++; } int dfs(int v, int f) { if(v == t) return f; vis[v] = 1; for(int i = head[v]; ~i; i = edge[i].next) { if(!vis[edge[i].v] && edge[i].c > 0) { int d = dfs(edge[i].v, min(f, edge[i].c)); if(d > 0) { edge[i].c -= d; edge[i+1].c += d; return d; } } } return 0; } int max_flow() { int flow = 0; while(1) { memset(vis, 0, sizeof(vis)); int tf = dfs(s, 2147483647); if(tf == 0) return flow; flow += tf; } return flow; } int main() { // freopen("in", "r", stdin); int u, v, c; while(~scanf("%d %d", &m, &n)) { init(); for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &c); adde(u, v, c); } s = 1; t = n; printf("%d\n", max_flow()); } return 0; }
随后索性全部删掉一切从简,改用最简单的邻接矩阵。利用BFS,第一次接触到汇点的那条路径一定是最短的(因为BFS是层进的)。找到了这条路并且记录下来即可。
接着,从源向外发出一个流(一定要足够大),按照之前BFS到的最短增广路流向汇点,根据短板效应找到流量,更新到最大流量上之后再更新残余网络(直接在原网络上更新即可)。下图可以比较清晰地说明这一点:
/* ━━━━━┒ギリギリ♂ eye! ┓┏┓┏┓┃キリキリ♂ mind! ┛┗┛┗┛┃\○/ ┓┏┓┏┓┃ / ┛┗┛┗┛┃ノ) ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┃┃┃┃┃┃ ┻┻┻┻┻┻ */ #include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; #define fr first #define sc second #define cl clear #define BUG puts("here!!!") #define W(a) while(a--) #define pb(a) push_back(a) #define Rint(a) scanf("%d", &a) #define Rs(a) scanf("%s", a) #define Cin(a) cin >> a #define FRead() freopen("in", "r", stdin) #define FWrite() freopen("out", "w", stdout) #define Rep(i, len) for(int i = 0; i < (len); i++) #define For(i, a, len) for(int i = (a); i < (len); i++) #define Cls(a) memset((a), 0, sizeof(a)) #define Clr(a, x) memset((a), (x), sizeof(a)) #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) #define lrt rt << 1 #define rrt rt << 1 | 1 #define pi 3.14159265359 #define RT return #define lowbit(x) x & (-x) #define onecnt(x) __builtin_popcount(x) typedef long long LL; typedef long double LD; typedef unsigned long long ULL; typedef pair<int, int> pii; typedef pair<string, int> psi; typedef pair<LL, LL> pll; typedef map<string, int> msi; typedef vector<int> vi; typedef vector<LL> vl; typedef vector<vl> vvl; typedef vector<bool> vb; typedef struct Edge { int u, v, c, next; }Edge; const int inf = 0x7f7f7f7f; const int maxn = 220; int cnt, head[maxn]; int cur[maxn], dd[maxn]; Edge edge[maxn*maxn*2]; int N, S, T; void init() { memset(head, -1, sizeof(head)); for(int i = 0; i < maxn; i++) edge[i].next = -1; } void adde(int u, int v, int c, int c1) { edge[cnt].u = u; edge[cnt].v = v; edge[cnt].c = c; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].u = v; edge[cnt].v = u; edge[cnt].c = c1; edge[cnt].next = head[v]; head[v] = cnt++; } bool bfs(int s, int t, int n) { queue<int> q; for(int i = 0; i < n; i++) dd[i] = inf; dd[s] = 0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edge[i].next) { if(dd[edge[i].v] > dd[u] + 1 && edge[i].c > 0) { dd[edge[i].v] = dd[u] + 1; if(edge[i].v == t) return 1; q.push(edge[i].v); } } } return 0; } int dinic(int s, int t, int n) { int st[maxn], top; int u; int flow = 0; while(bfs(s, t, n)) { for(int i = 0; i < n; i++) cur[i] = head[i]; u = s; top = 0; while(cur[s] != -1) { if(u == t) { int tp = inf; for(int i = top - 1; i >= 0; i--) { tp = min(tp, edge[st[i]].c); } flow += tp; for(int i = top - 1; i >= 0; i--) { edge[st[i]].c -= tp; edge[st[i] ^ 1].c += tp; if(edge[st[i]].c == 0) top = i; } u = edge[st[top]].u; } else if(cur[u] != -1 && edge[cur[u]].c > 0 && dd[u] + 1 == dd[edge[cur[u]].v]) { st[top++] = cur[u]; u = edge[cur[u]].v; } else { while(u != s && cur[u] == -1) { u = edge[st[--top]].u; } cur[u] = edge[cur[u]].next; } } } return flow; } int n, m; int G[maxn][maxn]; int main() { // FRead(); int u, v, w; while(~Rint(m) && ~Rint(n)) { Cls(G); S = 0, N = n, T = n - 1; init(); Rep(i, m) { Rint(u); Rint(v); Rint(w); G[u-1][v-1] += w; } Rep(i, n) { Rep(j, n) { if(G[i][j] != 0) adde(i, j, G[i][j], 0); } } printf("%d\n", dinic(S, T, N)); } RT 0; }
Dinic
相关文章推荐
- 黑马程序员--Java基础--网络编程java.net
- Android中判断app是否连接网络
- TCP 的那些事儿(下)
- 计算机网络之面试常考题
- TCP 的那些事儿(上)
- System.Transactions.TransactionException: 该伙伴事务管理器已经禁止了它对远程/网络事务的支持。
- C#异步,多线程下的HttpContext丢失问题
- Wireshark过滤规则之:http数据包
- HDU 3277 Marriage Match III 二分+网络流拆点
- TCP/IP传输层,你懂多少?
- HDU 3081 Marriage Match II 网络流+二分
- Openstack: gre网络细节
- iOS使用AFNetWorking获取网络数据时遇到的问题??
- HttpURLConnection往服务器发送请求
- HTTP响应头和请求头信息对照表
- Tomcat源码解读系列——Tomcat对HTTP请求处理的整体流程
- HttpCache缓存扩展方法
- 【读书笔记】iOS网络-使用推送通知
- 【读书笔记】iOS网络-使用推送通知
- Nginx编译安装第三方模块http_substitutions_filter_module