【模板】网络最大流

题目描述

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

输入输出格式

输入格式:

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

首先建边,我直接把反向边建好了;

边的结构体里依次存着{汇点,源点下一条边的位置,边权,反向边位置};

然后进入Dinic;

先bfs一遍,给每个店一个d(即从s点跑一个生成树的点深度);

然后只要能到达汇点,即d[t]!=0;

就找一遍增广路。

可能因为我一开始就把反向边建好了,所以有点慢。

为了模板的优秀与通用性,又敲了个更优美也更优异的。

代码实现:

 1 #include<cstdio>
 2 #include<cstring>
 3 int n,m,s,t,ans,d[10010];
 4 int a,b,c;
 5 int h[10010],hs,head,tail;
 6 struct edge{int s,n,v,r;}e[200010];
 7 struct queue{int s,d;}q[10010];
 8 int min(int x,int y){return x<y?x:y;}
 9 void bfs(int s,int t){
10     memset(d,0,sizeof(d));
11     head=tail=0;
12     q[head++]=(queue){s,1},d[s]=1;
13     while(head>tail){
14         a=q[tail].s,b=q[tail++].d;
15         for(int i=h[a];i;i=e[i].n) if(!d[e[i].s]&&e[i].v){
16             q[head++]=(queue){e[i].s,b+1};
17             d[e[i].s]=b+1;
18         }
19     }
20 }
21 int ap(int k,int t,int v){
22     if(k==t) return v;
23     int act=0;
24     for(int i=h[k];i;i=e[i].n) if(e[i].v&&d[e[i].s]==d[k]+1){
25         int ret=ap(e[i].s,t,min(v-act,e[i].v));
26         if(ret) e[i].v-=ret,e[e[i].r].v+=ret,act+=ret;
27     }
28     return act;
29 }
30 bool Dinic(int s,int t){
31     bfs(s,t);
32     if(!d[t]) return 0;
33     ans+=ap(s,t,1000000000);
34 }
35 int main(){
36     scanf("%d%d%d%d",&n,&m,&s,&t);
37     for(int i=1;i<=m;i++){
38         scanf("%d%d%d",&a,&b,&c);
39         e[++hs]=(edge){b,h[a],c,hs+1},h[a]=hs;
40         e[++hs]=(edge){a,h[b],0,hs-1},h[b]=hs;
41     }
42     while(Dinic(s,t));
43     printf("%d
",ans);
44     return 0;
45 }
第一版 432mm

第二版 233mm:

 1 #include<cstdio>
 2 #include<cstring>
 3 #define inf 1073741824
 4 int n,m,s,t,wt;
 5 int a,b,c;
 6 int d[10010],q[10010],head,tail;
 7 int h[10010],hs=1;
 8 struct edge{int s,n,w;}e[300000];
 9 inline int min(int x,int y){return x<y?x:y;}
10 void bfs(){
11     memset(d,0,sizeof(d));
12     head=tail=0;
13     d[s]=1,q[head++]=s;
14     while(head>tail){
15         a=q[tail++];
16         for(int i=h[a];i;i=e[i].n)
17         if(!d[e[i].s]&&e[i].w){
18             d[e[i].s]=d[a]+1;
19             if(e[i].s==t) return;
20             q[head++]=e[i].s;
21         }
22     }
23 }
24 int ap(int k,int nw){
25     if(k==t) return nw;
26     int bw=nw;
27     for(int i=h[k];i&&bw;i=e[i].n)
28     if(e[i].w&&d[e[i].s]==d[k]+1){
29         int dw=ap(e[i].s,min(bw,e[i].w));
30         if(dw) e[i].w-=dw,e[i^1].w+=dw,bw-=dw;
31         else d[e[i].s]=0;
32     }
33     return nw-bw;
34 }
35 bool Dinic(){
36     bfs();
37     if(!d[t]) return 0;
38     wt+=ap(s,inf);
39     return 1;
40 }
41 int main(){
42     scanf("%d%d%d%d",&n,&m,&s,&t);
43     for(int i=1;i<=m;i++){
44         scanf("%d%d%d",&a,&b,&c);
45         e[++hs]=(edge){b,h[a],c},h[a]=hs;
46         e[++hs]=(edge){a,h[b],0},h[b]=hs;
47     }
48     while(Dinic());
49     printf("%d
",wt);
50     return 0;
51 }

题目来源:洛谷

原文地址:https://www.cnblogs.com/J-william/p/6502009.html