zoukankan      html  css  js  c++  java
  • Drainage Ditches(最大流入门)

    Drainage Ditches(最大流入门)

     EK+邻接矩阵:

     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
    ",EK(1,n));
    62     }
    63     return 0;
    64 }
    View Code

    EK+前向星:

     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
    ",EK(1,n));
    66     }
    67     return 0;
    68 }
    View Code

    FF+邻接矩阵:

     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
    ",FF(1,n));
    45     }
    46     return 0;
    47 }
    View Code

    FF+邻接表:

     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
    ",FF(1,n));
    57     }
    58     return 0;
    59 }
    View Code

    FF+前向星: 

     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
    ",FF(1,n));
    53     }
    54     return 0;
    55 }
    View Code

    Dinic+邻接矩阵:

     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
    ",Dinic(1,n));
    62     }
    63     return 0;
    64 }
    View Code

     

    Dinic+邻接表:

     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
    ",Dinic(1,n));
    77     }
    78     return 0;
    79 }
    View Code

    Dinic+前向星:

     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
    ",Dinic(1,n));
    78     }
    79     return 0;
    80 }
    View Code

    Dinic+前向星+优化:

     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
    ",Dinic(1,n));
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    查看JVM使用的默认的垃圾收集器
    生产环境mysql的参数设置不一样,好好的程序,又出错
    伤秦姝行
    《道德经》全文——马王堆出土帛书版
    100篇锻炼口才表达能力的绕口令
    《道德经》部分
    40篇英语短文搞定3500个单词
    python浮点数与整数间的转化
    理解微积分
    matlab判断某个变量是否存在
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12447235.html
Copyright © 2011-2022 走看看