您的位置:首页 > 理论基础 > 计算机网络

[POJ1273]Drainage Ditches 网络流(最大流)

2015-11-13 11:31 411 查看
题目链接:http://poj.org/problem?id=1273

  网络流裸题,注意有重边。重边的处理方法很简单,就是将对应的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: