Drainage Ditches(最大流入门)

Drainage Ditches(最大流入门)

Drainage Ditches(最大流入门)

 

 EK+邻接矩阵:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define rep(i,first,last) for(int i=first;i<=last;i++)
 5 #define dep(i,first,last) for(int i=first;i>=last;i--)
 6 const int maxn=205;
 7 const int inf=0x3f3f3f3f;
 8 int graph[maxn][maxn];
 9 int pre[maxn];//记录前驱节点
10 int vis[maxn];
11 int n,m,a,b,flow;
12 
13 int BFS(int st,int ed){
14     memset(vis,0,sizeof(vis));
15     queue<int>que;
16     while(!que.empty()) que.pop();
17     que.push(st);
18     vis[st]=1;
19     int curr,flow=inf;
20     pre[st]=pre[ed]=-1;
21     while(!que.empty()){
22         curr=que.front();
23         que.pop();
24         if( curr==ed ) break;
25         rep(nxt,1,n){
26             if(!vis[nxt]&&graph[curr][nxt]!=0){
27                 vis[nxt]=1;
28                 if( flow>graph[curr][nxt]) flow=graph[curr][nxt];
29                 pre[nxt]=curr;
30                 que.push(nxt);
31             }
32         }
33     }
34     if(pre[ed]==-1) return -1;//没有找到增广路
35     return flow;
36 }
37 
38 int EK(int st,int ed){
39     int stream;
40     int sum=0;
41     while((stream=BFS(st,ed))!=-1 ){ //找到了增广路
42         int u=ed;
43         while( pre[u]!=-1 ){
44             graph[pre[u]][u]-=stream;//改变正向边的容量
45             graph[u][pre[u]]+=stream;//改变反向边的容量
46             u=pre[u];
47         }
48         sum += stream;
49     }
50     return sum;
51 }
52 int main()
53 {
54     while(~scanf("%d%d",&m,&n)){
55         memset(graph,0,sizeof(graph));
56         memset(vis,0,sizeof(vis));
57         while( m-- ){
58             scanf("%d%d%d",&a,&b,&flow);
59             graph[a][b]+=flow;//此处注意可能出现多条同一起点终点的情况
60         }
61         printf("%d\n",EK(1,n));
62     }
63     return 0;
64 }
View Code

EK+前向星:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int head[maxn<<1],cnt;
 9 struct node{int to,nxt,val;}e[maxn<<1];
10 void addedge(int u,int v,int val){
11     e[cnt].to=v;
12     e[cnt].val=val;
13     e[cnt].nxt=head[u];
14     head[u]=cnt++;
15 }
16 int vis[maxn],pre[maxn];
17 int BFS(int st,int ed){
18     memset(vis,0,sizeof(vis));
19     vis[st]=1;
20     queue<int>que;
21     while(!que.empty()) que.pop();
22     que.push(st);
23     int u,v,flow=inf;
24     pre[st]=pre[ed]=-1;
25     while(!que.empty()){
26         u=que.front();
27         que.pop();
28         if( u==ed ) break;
29         for(int i=head[u];~i;i=e[i].nxt ){
30             v=e[i].to;
31             if(!vis[v]&&e[i].val>0){
32                 vis[v]=1;
33                 flow=min(flow,e[i].val);
34                 pre[v]=i;//注意是i,不是u
35                 que.push(v);
36             }
37         }
38     }
39     if( pre[ed]==-1 ) return -1;
40     return flow;
41 }
42 int EK(int st,int ed){
43     int stream,flow=0;
44     while((stream=BFS(st,ed))!=-1 ){
45         //pre通过节点存边的坐标,通过边的反向边的to获取上一个节点
46         for(int i=pre[ed];~i;i=pre[e[i^1].to]){
47             e[i].val-=stream;
48             e[i^1].val+=stream;
49         }
50         flow+=stream;
51     }
52     return flow;
53 }
54 int main()
55 {
56     int a,b,n,m,flow;
57     while(~scanf("%d%d",&m,&n)){
58         memset(head,-1,sizeof(head));
59         cnt=0;
60         while( m-- ){
61             scanf("%d%d%d",&a,&b,&flow);
62             addedge(a,b,flow);
63             addedge(b,a,0);
64         }
65         printf("%d\n",EK(1,n));
66     }
67     return 0;
68 }
View Code

 

FF+邻接矩阵:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int graph[maxn][maxn];
 9 int vis[maxn];
10 int n,m;
11 int dfs(int st,int ed,int f){//在没有走到汇点前我们不知道流量是多少,所以f是动态更新的
12     vis[st]=1;
13     if(st==ed) return f;//走到汇点返回本次增广的流量
14     rep(i,1,n){
15         if( graph[st][i]>0 && vis[i]==0 ){
16             int d=dfs(i,ed,min(graph[st][i],f));
17             if( d>0 ){//顺着流过去,要受一路上最小容量的限制
18                 graph[st][i]-=d;
19                 graph[i][st]+=d;
20                 return d;
21             }
22         }
23     }
24     return 0;//无法到汇点
25 }
26 int FF(int st,int ed){
27     int flow=0,curr;
28     while(1){
29         memset(vis,0,sizeof(vis));
30         curr=dfs(st,ed,inf);
31         if( curr==0 ) return flow;
32         flow+=curr;
33     }
34 }
35 int main()
36 {
37     int a,b,val;
38     while(~scanf("%d%d",&m,&n)){
39         memset(graph,0,sizeof(graph));
40         while(m--){
41             scanf("%d%d%d",&a,&b,&val);
42             graph[a][b]+=val;
43         }
44         printf("%d\n",FF(1,n));
45     }
46     return 0;
47 }
View Code

 

FF+邻接表:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 struct node{
 9     int to;
10     int flow;
11     int rev;//反向边在数组中的位置
12     node(){}
13     node(int to,int flow,int rev):to(to),flow(flow),rev(rev){}
14 };
15 vector<node>graph[maxn];
16 int vis[maxn];
17 int n,m;
18 void addedge(int from,int to,int val){
19     graph[from].push_back(node(to,val,graph[to].size()));
20     graph[to].push_back(node(from,0,graph[from].size()-1));
21 }
22 int dfs(int st,int ed,int f){
23     vis[st]=1;
24     if(st==ed)return f;
25     rep(i,0,graph[st].size()-1){
26         node &temp=graph[st][i];//注意必须用引用
27         if(!vis[temp.to] && temp.flow>0 ){
28             int d=dfs(temp.to,ed,min(f,temp.flow));
29             if( d>0 ){
30                 temp.flow-=d;
31                 graph[temp.to][temp.rev].flow+=d;
32                 return d;
33             }
34         }
35     }
36     return 0;
37 }
38 int FF(int st,int ed){
39     int flow=0,curr;
40     while(1){
41         memset(vis,0,sizeof(vis));
42         curr=dfs(st,ed,inf);
43         if( curr==0 ) return flow;
44         flow+=curr;
45     }
46 }
47 int main()
48 {
49     int a,b,val;
50     while(~scanf("%d%d",&m,&n)){
51         rep(i,1,n) graph[i].clear();
52         while( m-- ){
53             scanf("%d%d%d",&a,&b,&val);
54             addedge(a,b,val);
55         }
56         printf("%d\n",FF(1,n));
57     }
58     return 0;
59 }
View Code

 

FF+前向星: 

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 struct node{int to,nxt,c;}e[maxn<<1];
 9 int head[maxn<<1],cnt,vis[maxn];
10 void addedge(int u,int v,int val){
11     e[cnt].to=v;
12     e[cnt].c=val;
13     e[cnt].nxt=head[u];
14     head[u]=cnt++;
15 }
16 int dfs(int st,int ed,int f){
17     vis[st]=1;
18     if(st==ed) return f;
19     for(int i=head[st];~i;i=e[i].nxt){
20         int v=e[i].to,val=e[i].c;
21         if( !vis[v]&&val>0 ){
22             int d=dfs(v,ed,min(val,f));
23             if( d>0 ){
24                 e[i].c-=d;
25                 e[i^1].c+=d;
26                 return d;
27             }
28         }
29     }
30     return 0;
31 }
32 int FF(int st,int ed){
33     int flow=0,d;
34     while(1){
35         memset(vis,0,sizeof(vis));
36         d=dfs(st,ed,inf);
37         if(d==0) return flow;
38         flow+=d;
39     }
40 }
41 int main()
42 {
43     int n,m,a,b,val;
44     while(~scanf("%d%d",&m,&n)){
45         memset(head,-1,sizeof(head));
46         cnt=0;
47         while( m-- ){
48             scanf("%d%d%d",&a,&b,&val);
49             addedge(a,b,val);
50             addedge(b,a,0);
51         }
52         printf("%d\n",FF(1,n));
53     }
54     return 0;
55 }
View Code

 

Dinic+邻接矩阵:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int graph[maxn][maxn];
 9 int step[maxn];//相当于将图分层了
10 int n,m;
11 bool bfs(int st,int ed){//bool 函数是一个小优化,判断是否能搜到汇点,如果连汇点都搜不到还dfs干什么
12     memset(step,-1,sizeof(step));
13     queue<int>que;
14     while(!que.empty()) que.pop();
15     step[st]=0;
16     que.push(st);
17     while(!que.empty()){
18         int curr=que.front();
19         que.pop();
20         rep(i,1,n){
21             if(graph[curr][i]>0 && step[i]==-1 ){
22                 step[i]=step[curr]+1;
23                 if( i==ed ) return true;
24                 que.push(i);
25             }
26         }
27     }
28     return step[ed]!=-1;
29 }
30 int dfs(int st,int ed,int f){
31     if(st==ed||f==0) return f;
32     int flow=0,d;
33     rep(i,1,n){
34         if((step[i]==step[st]+1)&&graph[st][i]>0&&(d=dfs(i,ed,min(graph[st][i],f)))){//step[i]==step[st]+1;控制仅允许流向下一层
35             graph[st][i]-=d;
36             graph[i][st]+=d;
37             flow+=d;//累加当前节点的某条路径的合适流量
38             f-=d;//当前节点的容量减去某条路径的合适流量
39             if(f==0) break;//如果当前节点的容量用完,说明无法再通过任何流量
40         }
41     }
42     if( flow==0 ) step[st]=inf;//如果当前节点无任何流量通过,取消标记
43     return flow;
44 }
45 int Dinic(int st,int ed){
46     int flow=0;
47     while(bfs(st,ed)){
48         flow+=dfs(st,ed,inf);
49     }
50     return flow;
51 }
52 int main()
53 {
54     int a,b,flow;
55     while(~scanf("%d%d",&m,&n)){
56         memset(graph,0,sizeof(graph));
57         while(m--){
58             scanf("%d%d%d",&a,&b,&flow);
59             graph[a][b]+=flow;
60         }
61         printf("%d\n",Dinic(1,n));
62     }
63     return 0;
64 }
View Code

 

Dinic+邻接表:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int step[maxn];
 9 struct node{
10     int to;
11     int flow;
12     int rev;//记录反向边的index
13     node(){}
14     node(int to,int flow,int rev):to(to),flow(flow),rev(rev){}
15 };
16 vector<node>graph[maxn];
17 int n,m;
18 void addedge(int from,int to,int flow){
19     graph[from].push_back(node(to,flow,graph[to].size()));
20     graph[to].push_back(node(from,0,graph[from].size()-1));
21 }
22 bool bfs(int st,int ed){
23     memset(step,-1,sizeof(step));
24     queue<int>que;
25     que.push(st);
26     step[st]=0;
27     while(!que.empty()){
28         int curr=que.front();
29         que.pop();
30         rep(i,0,graph[curr].size()-1){
31             node &temp=graph[curr][i];
32             if(step[temp.to]==-1 && temp.flow>0 ){
33                 step[temp.to]=step[curr]+1;
34                 if( temp.to==ed ) return true;
35                 que.push(temp.to);
36             }
37         }
38     }
39     return step[ed]!=-1;
40 }
41 int dfs(int st,int ed,int f){
42     if( st==ed || f==0 ) return f;
43     int flow=0;
44     rep(i,0,graph[st].size()-1){
45         node &temp=graph[st][i];
46         if( temp.flow>0 && step[temp.to]==step[st]+1){
47             int d=dfs(temp.to,ed,min(f,temp.flow));
48             if(d>0){
49                 temp.flow-=d;
50                 graph[temp.to][temp.rev].flow+=d;
51                 flow+=d;
52                 f-=d;
53                 if(f==0) break;
54             }
55         }
56     }
57     if( flow==0 ) step[st]=inf;
58     return flow;
59 }
60 int Dinic(int st,int ed){
61     int flow=0;
62     while(bfs(st,ed)){
63         flow+=dfs(st,ed,inf);
64     }
65     return flow;
66 }
67 int main()
68 {
69     int a,b,flow;
70     while(~scanf("%d%d",&m,&n)){
71         memset(graph,0,sizeof(graph));
72         while( m-- ){
73             scanf("%d%d%d",&a,&b,&flow);
74             addedge(a,b,flow);
75         }
76         printf("%d\n",Dinic(1,n));
77     }
78     return 0;
79 }
View Code

 

Dinic+前向星:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int head[maxn<<1],cnt,step[maxn];
 9 struct node{int to,nxt,c;}e[maxn<<1];
10 void addedge(int u,int v,int val){
11     e[cnt].to=v;
12     e[cnt].c=val;
13     e[cnt].nxt=head[u];
14     head[u]=cnt++;
15 }
16 bool bfs(int st,int ed){
17     memset(step,-1,sizeof(step));
18     queue<int>que;
19     while(!que.empty())que.pop();
20     que.push(st);
21     step[st]=0;
22     int u;
23     while(!que.empty()){
24         u=que.front();
25         que.pop();
26         for(int i=head[u];~i;i=e[i].nxt){
27             int v=e[i].to;
28             if( step[v]==-1 && e[i].c>0 ){
29                 step[v]=step[u]+1;
30                 que.push(v);
31                 if( v==ed ) return true;
32             }
33         }
34     }
35     return step[ed]!=-1;
36 }
37 
38 int dfs(int st,int ed,int flow){
39     if(st==ed||flow==0) return flow;
40     int curr=0;
41     for(int i=head[st];~i;i=e[i].nxt){
42         int v=e[i].to;
43         int val=e[i].c;
44         if( step[st]+1==step[v] && val>0 ){
45             int d=dfs(v,ed,min(val,flow));
46             if(d>0){
47                 e[i].c-=d;
48                 e[i^1].c+=d;//添反向边的时候是相邻的,i^1取相邻数;
49                 curr+=d;//累加当前节点的某条路径的合适流量
50                 flow-=d;//当前节点的容量减去某条路径的合适流量
51                 if(flow==0) break;//如果当前节点的容量用完,说明无法再通过任何流量
52             }
53         }
54     }
55     if( curr==0 ) step[st]=inf;//如果当前节点无任何流量通过,取消标记
56     return curr;
57 }
58 
59 int Dinic(int st,int ed){
60     int flow=0;
61     while(bfs(st,ed)){
62         flow+=dfs(st,ed,inf);
63     }
64     return flow;
65 }
66 int main()
67 {
68     int n,m,a,b,val;
69     while(~scanf("%d%d",&m,&n)){
70         memset(head,-1,sizeof(head));
71         cnt=0;
72         while(m--){
73             scanf("%d%d%d",&a,&b,&val);
74             addedge(a,b,val);
75             addedge(b,a,0);
76         }
77         printf("%d\n",Dinic(1,n));
78     }
79     return 0;
80 }
View Code

 

Dinic+前向星+优化:

Drainage Ditches(最大流入门)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const int inf=0x3f3f3f3f;
 6 #define rep(i,first,last) for(int i=first;i<=last;i++)
 7 #define dep(i,first,last) for(int i=first;i>=last;i--)
 8 int head[maxn<<1],cnt,step[maxn],cur[maxn];
 9 struct node{int to,nxt,c;}e[maxn<<1];
10 void addedge(int u,int v,int val){
11     e[cnt].to=v;
12     e[cnt].c=val;
13     e[cnt].nxt=head[u];
14     head[u]=cnt++;
15 }
16 bool bfs(int st,int ed){
17     memset(step,-1,sizeof(step));
18     queue<int>que;
19     while(!que.empty())que.pop();
20     que.push(st);
21     step[st]=0;
22     int u;
23     while(!que.empty()){
24         u=que.front();
25         que.pop();
26         for(int i=head[u];~i;i=e[i].nxt){
27             int v=e[i].to;
28             if( step[v]==-1 && e[i].c>0 ){
29                 step[v]=step[u]+1;
30                 que.push(v);
31                 if( v==ed ) return true;
32             }
33         }
34     }
35     return step[ed]!=-1;
36 }
37 
38 int dfs(int st,int ed,int flow){
39     if(st==ed||flow==0) return flow;
40     int curr=0;
41     for(int &i=cur[st];~i;i=e[i].nxt){
42         int v=e[i].to;
43         int val=e[i].c;
44         if( step[st]+1==step[v] && val>0 ){
45             int d=dfs(v,ed,min(val,flow));
46             if(d>0){
47                 e[i].c-=d;
48                 e[i^1].c+=d;
49                 curr+=d;
50                 flow-=d;
51                 if(flow==0) break;
52             }
53         }
54     }
55     if( curr==0 ) step[st]=inf;
56     return curr;
57 }
58 
59 int Dinic(int st,int ed){
60     int flow=0;
61     while(bfs(st,ed)){
62         rep(i,0,maxn-2) cur[i]=head[i];
63         flow+=dfs(st,ed,inf);
64     }
65     return flow;
66 }
67 int main()
68 {
69     int n,m,a,b,val;
70     while(~scanf("%d%d",&m,&n)){
71         memset(head,-1,sizeof(head));
72         cnt=0;
73         while(m--){
74             scanf("%d%d%d",&a,&b,&val);
75             addedge(a,b,val);
76             addedge(b,a,0);
77         }
78         printf("%d\n",Dinic(1,n));
79     }
80     return 0;
81 }
View Code

 

上一篇:「JXOI2017」颜色


下一篇:Phone List