【LA11248 训练指南】网络扩容【最大流】

题意:

  给定一个有向网络,每条边均有一个容量。问是否存在一个从点1到点N,流量为C的流。如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流?

分析:

  先跑一遍最大流,如果最大流大于等于C,则输possible。如果最大流小于C,则表明需要修改边的流量。很显然,需要修改的弧一定是满流的弧。但是如果直接暴力会超时,所以我们可以有两个优化。

 1.第一次求完最大流以后,把每条弧的流量保存下来,每次修改完一条弧的容量以后,都从当前残量网络开始继续增广。

 2.每次不需要增广到最大流,当流量大于等于C的时候就停止增广(不过不加这个优化好像也没事,反正我没加··)

  

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <queue>
  6 #include <vector>
  7 
  8 using namespace std;
  9 const int maxn=100+10;
 10 const int maxm=20000+10;
 11 const int INF=2147000000;
 12 struct Dinic{
 13     int head[maxn],Next[maxm],to[maxm],from[maxm],cap[maxm],flow[maxm];
 14     int n,m,s,t,sz;
 15     bool vis[maxn];
 16     int d[maxn],cur[maxn];
 17     void init(int n){
 18         this->n=n;
 19         sz=-1;
 20         memset(head,-1,sizeof(head));
 21     }
 22     void add_edge(int a,int b,int c){
 23         ++sz;
 24         to[sz]=b;Next[sz]=head[a];head[a]=sz;
 25         cap[sz]=c;flow[sz]=0,from[sz]=a;;
 26         ++sz;
 27         to[sz]=a;Next[sz]=head[b];head[b]=sz;
 28         cap[sz]=c;flow[sz]=c,from[sz]=b;
 29     }
 30     bool BFS(){
 31         memset(vis,0,sizeof(vis));
 32         for(int i=0;i<=n;i++)d[i]=INF;
 33         queue<int>Q;
 34         d[s]=0,vis[s]=1;
 35         Q.push(s);
 36         while(!Q.empty()){
 37             int u=Q.front();Q.pop();
 38             for(int i=head[u];i!=-1;i=Next[i]){
 39                 int v=to[i];
 40                 if(cap[i]>flow[i]&&!vis[v]){
 41                     vis[v]=1;
 42                     d[v]=d[u]+1;
 43                     Q.push(v);
 44                 }
 45             }
 46         }
 47         return vis[t];
 48     }
 49     int DFS(int x,int a){
 50         if(x==t||a==0)return a;
 51         int Flow=0,f;
 52         for(int& i=cur[x];i!=-1;i=Next[i]){
 53             int v=to[i];
 54             if(d[v]==d[x]+1&&(f=DFS(v,min(a,cap[i]-flow[i])))>0){
 55                 Flow+=f;
 56                 flow[i]+=f;
 57                 flow[i^1]-=f;
 58                 a-=f;
 59                 if(a==0)break;
 60             }
 61         }
 62         return Flow;
 63     }
 64     int Maxflow(int s,int t){
 65         this->s=s;this->t=t;
 66         int Flow=0;
 67         while(BFS()){
 68             for(int i=0;i<=n;i++)cur[i]=head[i];
 69             Flow+=DFS(s,INF);
 70         }
 71         return Flow;
 72     }
 73 }dinic;
 74 struct Edge{
 75     int from,to;
 76     bool operator <(const Edge& rhs)const{
 77         return from<rhs.from||(from==rhs.from&&to<rhs.to);
 78     }
 79 };
 80 vector<Edge>ans;
 81 int kase,N,E,C;
 82 int main(){
 83     kase=0;
 84     while(scanf("%d%d%d",&N,&E,&C)!=EOF&&(N||E||C)){
 85         ++kase;
 86         printf("Case %d: ",kase);
 87         ans.clear();
 88         dinic.init(N);
 89         int u,v,c;
 90         for(int i=1;i<=E;i++){
 91             scanf("%d%d%d",&u,&v,&c);
 92             dinic.add_edge(u,v,c);
 93         }
 94         int Maxflow=dinic.Maxflow(1,N);
 95         if(Maxflow>=C){
 96             printf("possible
");
 97         }else{
 98             int FLOW[maxm];
 99             for(int i=0;i<=dinic.sz;i++){
100                 FLOW[i]=dinic.flow[i];
101             }
102             int CAP,c=C-Maxflow;
103             for(int i=0;i<=dinic.sz;i+=2){
104                 if(dinic.cap[i]==dinic.flow[i]){
105 
106                     for(int i=0;i<=dinic.sz;i++)dinic.flow[i]=FLOW[i];
107                     CAP=dinic.cap[i];
108                     dinic.cap[i]=C;
109                     dinic.cap[i^1]=C;
110                     Maxflow=dinic.Maxflow(1,N);
111                     if(Maxflow>=c){
112                         ans.push_back((Edge){dinic.from[i],dinic.to[i]});
113                     }
114                     dinic.cap[i]=CAP;
115                     dinic.cap[i^1]=CAP;
116                     for(int i=0;i<=dinic.sz;i++)dinic.flow[i]=FLOW[i];
117                 }
118             }
119             if(ans.size()==0){
120                 printf("not possible
");
121             }else{
122                 sort(ans.begin(),ans.end());
123                 printf("possible option:");
124                 for(int i=0;i<ans.size();i++){
125                     if(i!=0)printf(",");
126                     printf("(%d,%d)",ans[i].from,ans[i].to);
127                 }
128                 printf("
");
129             }
130         }
131     }
132 return 0;
133 }
View Code
原文地址:https://www.cnblogs.com/LQLlulu/p/9303479.html