LibreOJ 116 有源汇有上下界最大流 【模板】【上下界最大流】

调完样例后居然一次ac,感动啊...

这是一个模板题有两个点要注意

一是建图的时候要用+=而不能直接=,因为两个点之间的管道可能会多次叠加(特别是处理x和y的时候)

二是在最后算s的流出流量之和时要先把【t到s】和【s到t】的边删掉

像素好低啊。。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<deque>
  4 #define INF 1000000000
  5 using namespace std;
  6 
  7 int n,G[250][250],G2[250][250],max_flow,T,sum;
  8 
  9 int layer[250],vis[250];
 10 bool countlayer(int s){//还有没有增广路 
 11     memset(layer,0,sizeof(layer));
 12     deque<int> q;
 13     q.push_back(s); layer[s]=1;
 14     while(!q.empty()){
 15         int nd = q.front(); q.pop_front();
 16         if(nd==T) return true;
 17         for(int i=1;i<=n+2;i++){
 18             if(G[nd][i] && layer[i]==0){
 19                 layer[i]=layer[nd]+1;
 20                 q.push_back(i);
 21             }
 22         }
 23     }
 24     return false;
 25 }
 26 
 27 int dinic(int s){
 28     //cout<<"?"<<endl;
 29     while( countlayer(s) ){
 30     //    cout<<max_flow<<endl;
 31     //    cout<<"suc"<<endl;
 32         memset(vis,0,sizeof(vis));
 33         deque<int> q;
 34         q.push_back(s); vis[s]=1;
 35         while(!q.empty()){
 36             int nd=q.back();
 37             if(nd==T){//找到一条增广路 
 38                 int minflow=INF,u;
 39                 for(int i=0;i<q.size()-1;i++){//从上到下的最小管道 
 40                     int from=q[i],to=q[i+1];
 41                     if(G[from][to]<minflow){
 42                         minflow=G[from][to];
 43                         u=from;
 44                     }
 45                 }
 46                 //做增广 
 47                 for(int i=0;i<q.size()-1;i++){
 48                     int from=q[i],to=q[i+1];
 49                     G[from][to]-=minflow;
 50                     G[to][from]+=minflow;
 51                 }
 52                 max_flow+=minflow;
 53                 //回溯
 54                 while(!q.empty() && q.back()!=u ){
 55                     vis[q.back()]=0;
 56                     q.pop_back();
 57                 }    
 58             }
 59             else{//继续往下搜
 60                 int i;
 61                 for(i=1;i<=n+2;i++){
 62                     if( layer[nd]+1==layer[i] && vis[i]==0 && G[nd][i] ){
 63                         vis[i]=1;
 64                         q.push_back(i);
 65                         break;
 66                     }
 67                 }
 68                 if(i==n+3) q.pop_back();
 69             }
 70         }
 71     }
 72 }
 73 
 74 int main(){
 75     int m,s,t; cin>>n>>m>>s>>t;
 76     //x在n+1 ; y在n+2 
 77     for(int i=1;i<=m;i++){
 78         int u,v,lower,upper; cin>>u>>v>>lower>>upper;
 79         sum+=lower;
 80         G[u][v]+=upper-lower;//非必要弧
 81         G[u][n+1] += lower;
 82         G[n+2][v] += lower;//必要弧 
 83     }
 84     G[n+1][n+2] = G[t][s] = INF;
 85     
 86     for(int i=1;i<=n+2;i++){
 87         for(int j=1;j<=n+2;j++) G2[i][j]=G[i][j];
 88     }
 89     T=n+1;
 90     dinic(n+2);
 91     //cout<<max_flow<<" "<<sum<<endl;
 92     if(max_flow!=sum) cout<<"please go home to sleep"; 
 93     else{
 94         int sum1=0;
 95         //cout<<"!!! "<<G2[s][t]<<" "<<G[s][t]<<endl;
 96         G[s][t] = G[t][s] = 0;
 97         for(int i=1;i<=n+2;i++){
 98         //    cout<<G2[s][i]<<" "<<G[s][i]<<endl;
 99             sum1+=G2[s][i]-G[s][i];
100         }
101     //    cout<<sum1<<endl;
102         max_flow=0;
103         
104         T=t;
105         dinic(s);
106         cout<<sum1+max_flow;
107     }
108     
109     return 0;    
110 }
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9504585.html