有上下界的网络流学习笔记 – 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,不外这两道题都可以消耗流的灵巧逃脱上下界网状物流)

发表评论

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