有上下界的网络流学习笔记 – liu_runda

果真首要是为了本身的复习功课。

假定朗读者可以纯熟地玩底架。

有上下界的使联播流的古地块是”修长的”,咱们经过本人无常的F的初始流量来修长的本人实用的的流量。,最大/最小流量也可以从实用的的修长的,而不是必不可少的东西的。

另类的经用才能是源汇和冷漠的汇流(环流)的替换更冷漠的吸收率实用的流的求解,对立面积极分子汇的上下界使联播流都要用到为了才能.

  1. 被动的汇有上下界实用的流(即,环跑)

样品:本人使联播,找到每一细流,如此每个镶边的跑必然要是>李。<=Hi,每个点必然要充分发挥潜在的能力总流入量=总废止量(流量使守恒)(为了流的特点是环往复,无始无终).

为了算法是有上下界使联播流算法的根底,但愿咱们对算法受胎深刻的领会,对立面算法,如此,我背诵在大太空中解说该算法的思惟和特效药。

实用的流算法的古地块是将本人使失望流量使守恒的初始流修长的成充分发挥潜在的能力流量使守恒的流.

流量使守恒,即,每个点的总流入量=总废止量。

设想有实用的的淹没,这么必然充分发挥潜在的能力每条边的流量都大于价值流量的下限.因而咱们可以令每条边的流量价值流量下限,获取初始流量。,后来的建出为了流的残量使联播.(即:每条边的流量价值这条边的流量下限与流量下限之差)为了初始流无常的充分发挥潜在的能力流量使守恒,如此终极的实用的流必然是在为了初始流的根底上增大了若干边的流量使得所稍微充分发挥潜在的能力流量使守恒.

如此,咱们思索本人不安分的的残余物流量。,像这般使附加流与咱们的初始流合以充分发挥潜在的能力C

设想某个点在占有边流量价值下界的初始流中充分发挥潜在的能力流量使守恒,这点也充分发挥潜在的能力了附加流中间的跑使守恒。,

设想本人点比初始流中间的废止有更多的流入,则,这点在附加流中间的废止量大于

设想本人点在初始流中流入以内废止,x,如此,这点在附加流中间的废止量以内

         可以以为附加流中每一从u到v的在边缘的本人流量代表将原图中u到v的流量增大1

x的数值可以细目x的占有边,更实用的。,A[i]象征I在初始跑中间的流入废止。,A[I]的正和负表现流入私下的相干。,接下来,咱们运用本人[I]表现I在初始FLO中间的流入和废止。

可是,DIIC算法可以找到运动宿SA的最大流。,不克不及在原使联播上径直求本人这般的被动的汇且使失望流量使守恒的附加流.注意到附加流是在原使联播上使失望流量使守恒的,这激起了咱们在原始使联播以及添加若干镶边和点。,这些边和点用于了解交通流的限度局限。

详细地,设想本人点i在原使联播上的附加流中必要充分发挥潜在的能力流入量>废止量(初始流中流入量<废止量,A[i]<0),这么咱们必要给多的流入量找本人去处,因而咱们使被安排好本人i动身跑的镶边= -a[i]。设想[i]>0,即,咱们必要在附加流>流入中废止。,咱们必要让更多的资产废止。,因而咱们使被安排好任职培训i跑的镶边= a[i]

自然,咱们也必要有本人尊重来重行开端。,也一种方式可以得分我的镶边。,因而咱们新建本人杜撰源点ss和本人杜撰汇点tt(双写字母是为了和积极分子汇使联播流中间的源点s汇点t相区别).新建的得分i的边都从ss动身,从我的边得分本人点TT。或本人到TT。,任何本人都是人SS。,

TT镶边总流量的下限必然要价值UPP的下限。,因每个边都有两个正和负A[I]相当的奉献,如此,所稍微A[i]的和价值0。,即,以内0的总和的绝对事物=绝对事物O。

设想咱们能找到充分发挥潜在的能力新加和的的流,则边是满的。,正本流的分配是咱们必要的附加流。,“新加的边都满流”和”附加流合上初始流流行流量抵消的流”是均等的约束条件).

这么咱们怎样才能找到每一充实跑的镶边的新淹没呢?咱们可以看一眼设想,这般的流必然要是咱们证明的图的SS TT最大流。,因而跑ss到tt的最大流那就够了.设想最大流的上胶料价值ss动身的占有边的流量下限积和(此刻得分tt的边也必然满流,因这两分配边的流量下限积和相当).

经受住,每条边在实用的流中间的流量=体积下界+附加流中它的流量(即跑完dinic后来的所加反向边的权值).

信号(ZOJ2314 Reactor 凉爽的)

#include
#include
#include
usingnamespace std;
constint maxn=300,maxm=100000;
struct edge{
  int to,next,w,num;
LST[MACM]int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w,int 努姆)
  LST=num;
  LST=b;LSE].next=first[a];LSE].w=w;first[a]=len++;
  LST=num;
  LST=a;LSE].next=first[b];LSE].w=0最好者[B]=Le;
}
int vis[maxn],dis[maxn],q[maxn],head,tail,s,t,T;
bool bfs(){
  VIS[S]=++T;dis[s]=1;head=tail=0Q [尾]s;
  while(头)!=残余部分)
    int x=q[head++];
    for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
      if(LST [Pt] W&&VIS[LST[Pt] to)!=T){
    Vist[LST[Pt] to ]DIS[LST[Pt] to ]=DIS[X]1Q [尾]LST [Pt]
      }
    }
  }
  if(V[t]=t),first,sizeof(一)
  return VIS[T]T;
}
int dfs(int x,int 林)
  if(x==t){
    return lim;
  }
  int flow=0,a;
  for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
    最好者[ X ]=pt;
    if(LST〔Pt〕W&&dis[lst[pt].to]==dis[x]+1(a=DFS(LST [Pt])。,min(LST[Pt]),lim-淹没)
      LST〔Pt〕Wa;1].w+=a;flow+=a;
      if(flow==lim)return flow;
    }
  }
  return flow;
}
int dinic(){
  int ans=0,x;
  while(BFS)
    while(x=dfs(s,0x7f7f7f7f))ans+=x;
  return ans;
}
int 低[成绩斯],ANS[MACM]
int totflow[maxn],n,m;

void work(){
  memset(totflow,0,sizeof(totflow));
  memset(first,-1,sizeof(一)len=0;
  scanf("%d%d",&n,&m);
  int u,v,b;
  s=0;t=n+1;
  for(int i=1;i<=m;++i){
    scanf("%d%d%d%d",&u,&v,低[我],&b);
    addedge(u,v,b低[我],Ti流[U]=低[I];TutFLU[V]低[我]
  }
  int sum=0;
  for(int i=1;i<=n;++i){
    if(totflow[i]<0){
      addedge(i,t,-totflow[i],0);
    }else{
      sum+=totf低[我]
      addedge(s,i,totflow[i],0);
    }
  }
  if(第尼克)和)
    puts("YES");
    for(int i=1;i<=n;++i){
      for(int Pt=最好者[i];Pt!=-1;pt=LST [ Pt]。下一步)
    if(LST [Pt] num0||pt%2==0)continue;
    ANS[LST[Pt]·num ]=LST〔Pt〕W+低[LST[Pt]·num ]
      }
    }
    for(int i=1;i<=m;++i)printf("%d\n",ANS[I]
  }else puts("NO");
}
int main(){
  int 实验"%d",&试验)
  while(试验)){
    work();if(试验)标记出口"\n");
  }
  return0;
}

  2. 积极分子汇有上下界实用的流

样品:使联播现时有本人。源点s移交事项点T,找到每一细流使得源点的总废止量价值汇点的总流入量,对立面点充分发挥潜在的能力跑使守恒。,同时每条边的流量充分发挥潜在的能力上限和下界限度局限.

源和汇使失望流量使守恒。,这使咱们很难做到这点。,因而咱们想办法把成绩转变成轻易处置的每个点都充分发挥潜在的能力流量使守恒的被动的汇局面.

为了使源汇充分发挥潜在的能力流量使守恒,咱们必要有镶边流入点S。,T.曾经注意到S的废止价值T的流入。,咱们就可以从汇点t向源点s连每一下界为0上限为无量大的边,相当于把从源点s废止的流量再流记起.在这般的图中套用上面的算法求出本人实用的的环流,经过将T从汇点移除到源点S,本人实用的的Act

这时有本人小成绩:倡议CON的终极实用的流量是多少?

可以找到,在环流中必然要充分发挥潜在的能力S废止的总流量。,假定原始图中缺少边流入S。,S废止的跑是从T到S的神边流。,更确切地说s-t实用的流的流量.因而咱们经受住看一下t到s的无量边的流量(即dinic跑完后来的反向边的权值)那就够了知情原图中积极分子汇实用的流的流量.

信号:为了实用的流算法在积极分子汇有上下界最大流/最小流中首都用到,你可以布告上面两个算法的信号。

3.积极分子汇有上下界最大流

样品:使联播现时有本人。源点s移交事项点T,找到每一细流使得源点的总废止量价值汇点的总流入量,对立面点充分发挥潜在的能力跑使守恒。,同时每条边的流量充分发挥潜在的能力上限和下界限度局限.在这些假设的事情下断言总流量最大的量、体积、强度等.

率先套用上面的算法求出本人积极分子汇有上下界实用的流.此刻的流无常的最大.

接下来,在残余物使联播上运转S-最大流。

终极的最大流流量=实用的流流量(即t到s的无量在边缘跑出的流量)+新增广出的s-t流量

成绩:当某个边使失望TR的下限时,它会添加吗?

不熟练的.因咱们一开端建的图执意把上胶料价值流量下限的流量拿出去后来的的残量使联播,形象的中间的交通并不。

信号:ZOJ 3229 Shoot The Bullet 东方文花帖 (因ZoJ的评价可插件如同挂起了。,我不知情我设想特赞。,请慎重的。

#include
#include
#include
usingnamespace std;
constint maxn=2005,maxm=100005;
constint inf=0x7f7f7f7f;
struct edge{
  int to,next,w,num;
LST[MACM]int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w,int 努姆)
  LST=num;
  LST=b;LSE].next=first[a];LSE].w=w;first[a]=len++;
  LST=num;
  LST=a;LSE].next=first[b];LSE].w=0最好者[B]=Le;
}
int q[maxn],vis[maxn],dis[maxn],T,s,t,head,tail,ss,tt;
bool bfs(){
  head=tail=0;VIS[S]=++TQ [尾]s;
  while(头)!=残余部分)
    int x=q[head++];
    for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
      if(LST [Pt] W&&VIS[LST[Pt] to)!=T){
    Vist[LST[Pt] to ]DIS[LST[Pt] to ]=DIS[X]1Q [尾]LST [Pt]
      }
    }
  }
  if(V[t]=t),first,sizeof(一)
  return VIS[T]T;
}
int dfs(int x,int 林)
  if(x==t)return lim;
  int flow=0,a;
  for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
    最好者[ X ]=pt;
    if(LST〔Pt〕W&&dis[lst[pt].to]==dis[x]+1(a=DFS(LST [Pt])。,min(LST[Pt]),lim-淹没)
      LST〔Pt〕Wa;1].w+=a;flow+=a;
      if(flow==lim)return flow;
    }
  }
  return flow;
}
int dinic(){
  int ans=0,x;
  while(BFS)
    while(x=dfs(s,INF)x;
  return ans;
}
int totflow[maxn];
void Add(int a,int b,int lo,int hi,int 努姆)
  totflow[a]ToFLUT[B]lo;
  addedge(a,b,hi-lo,努姆)
}
int 低[成绩斯],ANS[MACM]
int n,m,tot;
void bound_flow(){
  int sum=0;
  for(int i=s;i<=t;++i){
    if(totflow[i]<0){
      addedge(i,tt,-totflow[i],0);
    }else{
      sum+=totf低[我]
      addedge(ss,i,totflow[i],0);
    }
  }
  addedge(t,s,0x7f7f7f7f,0);
  int tmps=s,tmpt=t;
  sttt;
  if(第尼克)和)
    for(int Pt=最好者[SS];Pt!=-1;pt=LST [ Pt]。下一步)
      LST〔Pt〕WLST1].w=0;
    }
    for(int Pt=最好者[TT];Pt!=-1;pt=LST [ Pt]。下一步)
      LST〔Pt〕WLST1].w=0;
    }
    int flow0=LSE-1].w;
    LSE-1].w=LSE-2].w=0;
    sTMPStmpt;
    printf("%d\n",flow0+dinic());
    for(int i=1;i<=m;++i){
      for(int pt=first[i+n];pt!=-1;pt=LST [ Pt]。下一步)
    if(LST [Pt] num!=0){
      ANS[LST[Pt]·num ]=LST〔Pt〕W+低[LST[Pt]·num ]
    }
      }
    }
    for(int i=1;i<=tot;++i)printf("%d\n",ANS[I]
  }else{
    printf("-1\n");
  }
}

void work(){
  s=0;t=n+m+1;
  ss=n+m+2;tt=n+m+3;
  memset(first,-1,sizeof(一)len=0;
  memset(totflow,0,sizeof(totflow));
  int x,y;
  for(int i=1;i<=m;++i){
    scanf("%d",&x);
    添加(n)+i,t,x,inf,0);
  }
  int l,h;
  tot=0;
  for(int i=1;i<=n;++i){
    scanf("%d%d",&x,&y);
    添加(S),i,0,y,0);
    for(int j=1;j<=x;++j){
      ++tot;
      scanf("%d%d%d",&y,&l,&h);
      添加(i),n+y+1,l,h,低;l;
    }
  }
  bound_flow();printf("\n");
}
int main(){
  while(斯坎夫"%d%d",&n,&m)!=EOF任务
  return0;
}

4.积极分子汇有上下界最小流

样品:使联播现时有本人。源点s移交事项点T,找到每一细流使得源点的总废止量价值汇点的总流入量,对立面点充分发挥潜在的能力跑使守恒。,同时每条边的流量充分发挥潜在的能力上限和下界限度局限.在这些假设的事情下断言最小总流量.

依然是先跑出本人积极分子汇实用的流.这时候的流也无常的是最小的.假设咱们能在残量使联播上找到每一s-t的渠道使得敷衍这条渠道上的流量后来的依然充分发挥潜在的能力流量下限,咱们就可以流行本人更小的流.仿佛咱们并缺少什么算法可以”找到放量多的能去除流量的渠道”

这时候必要咱们再了解一下dinic的反向边.反向边的流量添加均等于正向边的的流量减缩.因而咱们在残量使联播上找出t到s的流就相当于减小了s到t的流,因而咱们在跑出实用的流的残量使联播上跑t-s最大流,用实用的流的上胶料减去在这场合t-s最大流的上胶料执意最小流的上胶料.(t-s最大流果真是放量减缩s-t任职培训的流).

问:它会减缩交通到下限的交通吗?

不,它与最大流量的下限和下限胜任的。,咱们曾经发生了初始流量从每一侧的交通与SIZ。,这些流量缺席咱们建出的图中.最顶点的局面是减缩到占有边的流量价值流量下限,它不熟练的更小。

信号:bzoj2502 清扫雪路

#include
#include
#include
usingnamespace std;
constint maxn=205,maxm=100005;
struct edge{
  int to,next,w;
LST[MACM]int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w){//PrdTf(添加 %d %d\n",a,b);
  LST=b;LSE].next=first[a];LSE].w=w;first[a]=len++;
  LST=a;LSE].next=first[b];LSE].w=0最好者[B]=Le;
}
int q[maxn],vis[maxn],dis[maxn],head,tail,s,t,T,ss,tt;
bool bfs(){
  head=tail=0;VIS[S]=++T;dis[s]=1Q [尾]s;
  while(头)!=残余部分)
    int x=q[head++];
    for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
      if(LST [Pt] W&&VIS[LST[Pt] to)!=T){
    Vist[LST[Pt] to ]DIS[LST[Pt] to ]=DIS[X]1Q [尾]LST [Pt]
      }
    }
  }
  if(V[t]=t),first,sizeof(一)
  return VIS[T]T;
}
int dfs(int x,int 林)
  if(x==t)return lim;
  int flow=0,a;
  for(int Pt=最好者[X];Pt!=-1;pt=LST [ Pt]。下一步)
    最好者[ X ]=pt;
    if(LST〔Pt〕W&&dis[lst[pt].to]==dis[x]+1(a=DFS(LST [Pt])。,min(LST[Pt]),lim-淹没)
      LST〔Pt〕Wa;1].w+=a;flow+=a;
      if(flow==lim)return flow;
    }
  }
  return flow;
}
int dinic(){
  int ans=0,x;
  while(BFS){
    while(x=dfs(s,0x7f7f7f7f))ans+=x;
  }
  return ans;
}
int totflow[maxn];
void del(int x){
  for(int Pt=最好者[X];Pt!=-1;pt=lst[pt].next)LST〔Pt〕WLST1].w=0;
}
int main(){
  int 斯堪夫"%d",&n);
  int x,y;
  memset(first,-1,sizeof(一)
  for(int i=1;i<=n;++i){
    scanf("%d",&x);
    for(int j=1;j<=x;++j){
      scanf("%d",&y);
      totflow[i]--;totflow[y]++;
      addedge(i,y,0x7f7f7f7f);
    }
  }

  s=0;t=n+1;ss=n+2,tt=n+3;
  for(int i=1;i<=n;++i){
    addedge(s,i,0x7f7f7f7f);
    addedge(i,t,0x7f7f7f7f);
  }
  for(int i=1;i<=n;++i){
    if(totflow[i]<0){
      addedge(i,tt,-totflow[i]);
    }else{
      addedge(ss,i,totflow[i]);
    }
  }
  addedge(t,s,0x7f7f7f7f);
  int tmps=s,tmpt=t;
  sttt;
  dinic();
  int flow0=LSE-1].w;
  LSE-1].w=LSE-2].w=0;
  Del(SS)
  s甲状旁腺功用机能亢进tmps;
  printf("%d\n",flow0-dinic());
  return0;
}

5.积极分子汇有上下界费流(待填坑,bzoj3876和Codeforces 708D,不外这两道题都可以消耗流的才能废止上下界使联播流)

发表评论

电子邮件地址不会被公开。 必填项已用*标注