有源汇有上下界最大流 (ZQU1591)

题意:现在的网络有一个源点s和汇点t,求出一个流使得源点的总流出量等于汇点的总流入量,其他的点满足流量守恒,而且每条边的流量满足上界和下界限制.

思路:要满足每一个点的流量守恒,我们可以尝试像无源汇上下界可行流一样,跑一次dinic先构造出这样一个的可行流。在保证他可行的情况下,利用残余流量

从s到t再跑一次dinic即可;  这个时候跑的dinic 在上一次跑的时候,从t到s就有了一定的流量,所以他的反向边,也就是s到t在跑第二次dinic的时候,就已经保存了

上一次跑dinic的值,所以这一次跑,会将剩下的参与流量尽可能的流向t 来求出最大流。

那为什么这样子可行呢?

我们在第一次跑的时候,就已经保证了从超级源点到超级汇点的值(也就是S,T)是不变的了;

也就是在保证可行流的情况下,再进行操作,保证最大而已。

  1 #include<cstdio>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<math.h>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=11000;
  8 const int inf=0x3f3f3f3f;
  9 int head[maxn],level[maxn];   //前者为邻接表必要数据,后者为dinic的层 数据
 10 int limit[maxn];  //limit为该点的流量   小于0的时候是流出多
 11 int num;  //邻接表
 12 int cur[maxn];
 13 void init()
 14 {
 15     num=-1  ;
 16     memset(head,-1,sizeof(head));
 17 }
 18 struct node
 19 {
 20     int v,w,next;
 21 }G[400000];
 22 int bfs(int s,int t)
 23 {
 24     queue<int>q;
 25     q.push(s);
 26     memset(level,-1,sizeof(level));
 27     level[s]=0;
 28     while(!q.empty()){
 29         int u=q.front();
 30         q.pop();
 31         for(int i=head[u];i!=-1;i=G[i].next){
 32             int v=G[i].v;
 33             if(G[i].w>0&&level[v]==-1){
 34                 level[v]=level[u]+1;
 35                 q.push(v);
 36             }
 37         }
 38     }
 39    return level[t];
 40 }
 41 int dfs(int s,int t,int f)
 42 {
 43     if(s==t) return f;
 44     int ans=0;
 45     for(int i=cur[s];i!=-1;i=G[i].next){
 46         cur[s]=i;  //当前弧优化;
 47         int v=G[i].v;
 48         if(G[i].w>0&&level[s]+1==level[v]){
 49             int d=dfs(v,t,min(G[i].w,f-ans));
 50             if(d>0){
 51                 G[i].w-=d;
 52                 G[i^1].w+=d;
 53                 ans+=d;
 54                 if(ans==f) return ans;
 55             }
 56         }
 57     }
 58     if(ans==0) level[s]=0;
 59     return ans;
 60 }
 61 int dinic(int s,int t)
 62 {
 63     int ans=0;
 64     while(1){
 65         int temp=bfs(s,t);
 66         if(temp==-1) break;
 67         memcpy(cur,head,sizeof(cur));
 68         ans+=dfs(s,t,inf);
 69     }
 70     return ans;
 71 }
 72 void build(int u,int v,int w)
 73 {
 74     num++;
 75     G[num].v=v;
 76     G[num].w=w;
 77     G[num].next=head[u];
 78     head[u]=num;
 79 
 80     num++;
 81     G[num].v=u;
 82     G[num].w=0;
 83     G[num].next=head[v];
 84     head[v]=num;
 85 }
 86 int main()
 87 {
 88     init();
 89     int n,m,s,t;
 90     scanf("%d%d%d%d",&n,&m,&s,&t);
 91     for(int i=1;i<=m;i++){
 92         int u,v,w1,w2;
 93         scanf("%d%d%d%d",&u,&v,&w1,&w2);
 94         limit[u]-=w1;
 95         limit[v]+=w1;
 96         build(u,v,w2-w1);
 97     }
 98     build(t,s,inf);
 99     //其实这里应该有上面的limit的变化 只是因为这里的w1为0,所以省略不写。
100     int S=0;int T=n+1;
101     int sum=0;
102     for(int i=1;i<=n;i++){
103         if(limit[i]<0) build(i,T,-limit[i]);
104         if(limit[i]>0) build(S,i,limit[i]),sum+=limit[i];
105     }
106     if(dinic(S,T)!=sum) printf("please go home to sleep\n");
107     else printf("%d\n",dinic(s,t));
108     return 0;
109 }

 

posted @ 2019-11-06 21:34  古比  阅读(120)  评论(0编辑  收藏  举报