有上下界的网络流学习笔记 – 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,不外这两道题都可以花费的钱流的熟练逃脱上下界电网流)

发表评论

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