题目描述

如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入输出格式

输入格式:

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)

输出格式:

一行,包含一个正整数,即为该网络的最大流。

输入输出样例

输入样例#1: 复制
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
输出样例#1: 复制
50

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=25

对于70%的数据:N<=200,M<=1000

对于100%的数据:N<=10000,M<=100000

样例说明:

题目中存在3条路径:

4-->2-->3,该路线可通过20的流量

4-->3,可通过20的流量

4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)

故流量总计20+20+10=50。输出50。

原本不打算看网络流,下午帮沈爷爷debug的时候顺便学了一下。

这里写的是DINIC算法。

大概分为BFS 和 DFS 两部分。

BFS主要是用来给图来分层,就是存一下每个点的深度。

代码如下:

 1 queue<ll>qq;
 2 bool bfs() {
 3 
 4     while(!qq.empty()) qq.pop();
 5     memset(dep,0,sizeof(dep));
 6     dep[s] = 1;
 7     qq.push(s);
 8     while(!qq.empty()) {
 9         ll u = qq.front();
10         qq.pop();
11         for(int i = head[u]; ~i ; i = e[i].nxt) {
12             if(e[i].c and dep[e[i].v] == 0) {
13                 dep[e[i].v] = dep[u] + 1;
14                 qq.push(e[i].v);
15             }
16         }
17     }
18     return dep[t];
19 }

而DFS就是来寻找增广路了。就是从源点来走,尽量将所有能走的边都走完。

代码如下:

 1 ll dfs(ll nd, ll val) {
 2     if(val == 0) return 0;
 3     if(nd == t) return val;
 4     for(int i = head[nd] ; ~i ; i = e[i].nxt) {
 5         ll u = e[i].v;
 6         if(dep[u] == dep[nd] + 1 and e[i].c) {
 7             ll k = dfs(u , min(e[i].c,val));
 8             if(k) {
 9                 e[i].c -= k;
10                 e[i ^ 1].c += k;
11                 return k;
12             }
13 
14         }
15     }
16     return 0;
17 }

经过我一下午的debug经验,这里重点强调一个问题

存反向边的时候,因为我们存边的时候是需要编号的,而且我们需要尽量快的找到反向边。所以我们在这里设e [ i ]为原有流量,设e [ i ^  1 ] 为反向边的流量。

但是这里就有问题了。如果我们第一个存下的边的编号设为 1 的话,那我们第一条边的反向边就是0了,而我们这样就返回不到第0条边。

同样,我们在遍历边的时候,我们就不能写成 for ( int i = head[ u ] ; i ; i = e[ i ]. nxt)了;

就必须写成for(  ; i>=0 ;  ) 或者 for(  ;  ~i  ;   )。

同样我们在存边的时候需要预处理一下head数组,初值最好设为-1, 否则会死循环。

完整代码如下:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 #include<queue>
 7 #include <iostream>
 8 using namespace std;
 9 typedef long long ll;
10 const ll maxn = 1e6 + 7;
11 #define inf 2147483647
12 ll read() {
13     ll a = 0, b = 1;
14     char c = getchar();
15     while(c < \'0\' or c > \'9\') {
16         if(c == \'-\') b = -1;
17         c = getchar();
18     }
19     while(c >= \'0\' and c <= \'9\') {
20         a = a * 10 + c - \'0\';
21         c = getchar();
22     }
23     return a * b;
24 }
25 ll dep[maxn],w[maxn],cnt = -1,n,m,s,ans,t,head[maxn];
26 struct node {
27     ll v,c,nxt;
28 } e[maxn];
29 void add(ll ai, ll bi, ll ci) {
30     e[++cnt].v = bi;
31     e[cnt].c = ci;
32     e[cnt].nxt = head[ai];
33     head[ai] = cnt;
34 }
35 queue<ll>qq;
36 bool bfs() {
37 
38     while(!qq.empty()) qq.pop();
39     memset(dep,0,sizeof(dep));
40     dep[s] = 1;
41     qq.push(s);
42     while(!qq.empty()) {
43         ll u = qq.front();
44         qq.pop();
45         for(int i = head[u]; ~i ; i = e[i].nxt) {
46             if(e[i].c and dep[e[i].v] == 0) {
47                 dep[e[i].v] = dep[u] + 1;
48                 qq.push(e[i].v);
49             }
50         }
51     }
52     return dep[t];
53 }
54 ll dfs(ll nd, ll val) {
55     if(val == 0) return 0;
56     if(nd == t) return val;
57     for(int i = head[nd] ; ~i ; i = e[i].nxt) {
58         ll u = e[i].v;
59         if(dep[u] == dep[nd] + 1 and e[i].c) {
60             ll k = dfs(u , min(e[i].c,val));
61             if(k) {
62                 e[i].c -= k;
63                 e[i ^ 1].c += k;
64                 return k;
65             }
66 
67         }
68     }
69     return 0;
70 }
71 int main() {
72     n = read();
73     m = read();
74     s = read();
75     t = read();
76     memset(head,-1,sizeof(head));
77     for(int i=1; i<=m; i++) {
78         ll t1,t2,t3;
79         t1 = read();
80         t2 = read();
81         t3 = read();
82         add(t1,t2,t3);
83         add(t2,t1,0);
84     }
85     while(bfs()) {
86         while(1) {
87             int d = dfs(s,inf);
88             if(d == 0) break;
89             else ans += d;
90         }
91     }
92     printf("%lld\n",ans);
93     return 0;
94 }