P3376 【模板】网络最大流dinic算法

 P3376 【模板】网络最大流

题目描述

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

输入输出格式

输入格式:

第一行包含四个正整数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。

分析

dinic算法,需要注意许多点:

  • 反向边初始值容量为0,
  • 异或符号,x^1,x为偶数+1,奇数-1;所以第一条边为偶数,所以我的第一条边是2,他的反向边是3;
  • 数据范围,这个就不多说了,反向建边,数组大小要乘2

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 20100;
 7 const int INF = 1e9;
 8 
 9 struct Edge{
10     int to,c,nxt;
11 }e[500100];
12 
13 int q[5000100],head[N],dis[N],cur[N];
14 int S,T,n,m,L,R,tot = 1;
15 
16 inline char nc() {
17     static char buf[100000],*p1 = buf,*p2 = buf;
18     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
19 }
20 inline int read() {
21     int x = 0,f = 1;char ch = nc();
22     for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1;
23     for (; ch>='0'&&ch<='9'; ch = nc()) x = x * 10 + ch - '0';
24     return x * f;
25 }
26 inline void add_edge(int u,int v,int w) {
27     e[++tot].to = v,e[tot].c = w,e[tot].nxt = head[u],head[u] = tot;
28     e[++tot].to = u,e[tot].c = 0,e[tot].nxt = head[v],head[v] = tot;
29 }
30 inline bool bfs() {
31     for (int i=1; i<=n; ++i) {
32         cur[i] = head[i];dis[i] = -1;
33     }
34     L = 1;R = 0;
35     q[++R] = S;
36     dis[S] = 0;
37     while (L <= R) {
38         int u = q[L++];
39         for (int i=head[u]; i; i=e[i].nxt) {
40             int v = e[i].to,c = e[i].c;
41             if (dis[v]==-1 && c>0) {
42                 q[++R] = v;
43                 dis[v] = dis[u] + 1;
44                 if (v==T) return true;
45             }
46         }
47     }
48     return false;
49 }
50 int dfs(int u,int flow) {
51     if (u==T) return flow;
52     int used = 0;
53     for (int & i=cur[u]; i; i=e[i].nxt) {
54         int v = e[i].to,c = e[i].c;
55         if (dis[v]==dis[u]+1 && c>0) {
56             int tmp = dfs(v,min(c,flow-used));
57             if (tmp > 0) {
58                 e[i].c -= tmp;e[i^1].c += tmp;
59                 used += tmp;
60                 if (used==flow) break;
61             }
62         } 
63     }
64     if (used != flow) dis[u] = -1;
65     return used;
66 }
67 inline int dinic() {
68     int ans = 0;
69     while (bfs())
70         ans += dfs(S,INF);
71     return ans;
72 }
73 int main() {
74     n = read(),m = read(),S = read(),T = read();
75     for (int a,b,c,i=1; i<=m; ++i) {
76         a = read(),b = read(),c = read();
77         add_edge(a,b,c);
78     }
79     printf("%d",dinic());
80     return 0;
81 }
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int MAXN = 100100;
 8 const int INF = 1e9;
 9 
10 struct Edge{
11     int to,c,nxt;
12     Edge(){}
13     Edge(int tt,int cc,int nn) {to = tt,c = cc,nxt = nn;}
14 }e[1000100];
15 queue<int>q;
16 
17 int head[MAXN],dis[MAXN];
18 int s,t,n,m,tot = 1;
19 
20 int read()
21 {
22     int x = 0, f = 1;char ch = getchar();
23     while (ch<'0'||ch>'9') {if (ch=='-') f = -1; ch = getchar();}
24     while (ch>='0'&&ch<='9') {x = x*10+ch-'0'; ch = getchar();}
25     return x*f;
26 }
27 bool bfs()
28 {
29     q.push(s);
30     memset(dis,-1,sizeof(dis));
31     dis[s] = 0;
32     while (!q.empty())
33     {
34         int u = q.front();
35         q.pop();
36         for (int i=head[u]; i; i=e[i].nxt)
37         {
38             int v = e[i].to;
39             if (dis[v]==-1&&e[i].c>0)
40             {
41                 dis[v] = dis[u]+1;
42                 q.push(v);
43             }
44         }
45     }
46     if (dis[t]!=-1) return true;
47     return false;
48 }
49 int dfs(int u,int low)
50 {
51     if (u==t) return low;
52     int w,used = 0;
53     for (int i=head[u]; i; i=e[i].nxt)
54     {
55         int v = e[i].to;
56         if (dis[v]==dis[u]+1&&e[i].c>0)
57         {
58             w = dfs(v,min(low-used,e[i].c));
59             e[i].c -= w;
60             e[i^1].c += w;
61             used += w;
62             if (used==low) return low;
63         }
64     }
65     if (!used) dis[u] = -1;
66     return used;
67 }
68 int dinic()
69 {
70     int ans = 0,t;
71     while (bfs())
72         ans += dfs(s,INF);
73     return ans;
74 }
75 int main()
76 {
77     n = read();m = read();s = read();t = read();
78     for (int u,v,w,i=1; i<=m; ++i)
79     {
80         u = read();v = read();w = read();
81         e[++tot] = Edge(v,w,head[u]);
82         head[u] = tot;
83         e[++tot] = Edge(u,0,head[v]);
84         head[v] = tot;    
85     }
86     printf("%d",dinic());
87     return 0;
88 }
很早以前的代码
原文地址:https://www.cnblogs.com/mjtcn/p/7256796.html