zoukankan      html  css  js  c++  java
  • 有上下界的网络流

    以下摘自Proverbs的博客:

    1. 首先进行构图,对于那么对流量没有限制的边,我们直接将容量赋值为原始的容量,而对于有流量要求的边,我们将容量减去下界并将其等价与无下界的边。

    2. 添加一个附加汇点和一个附加源点,从附加源点连向每个顶点的容量为以该点所有流入的下界流量总和,每个顶点流向附加汇点是该点流出的下界流量总和。

    3. 添加一条从汇点到源点流量为INF的边,这条边的意义在于,能够使得源点会汇点满足成为流量平衡条件的普通节点。

    4. 我们在以附加源点和附加汇点求一次最大流,如果所有的到附加汇点的边都满载,那么说明这个网络是存在满足所有下界的可行流的。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using std::min;
      5 using std::max;
      6 #define M 100000
      7 #define N 1000
      8 #define INF 210000000
      9 #define rep(i,n) for(int i=1;i<=(n);i++)
     10 #define mem(a) memset(a,0,sizeof(a))
     11 int len[M <<1],e[M <<1],nex[M <<1],other[M <<1],head[N],last[N],d[N],num[N];
     12 int rdu[N],cdu[N],_,eee,flag,y,k,l,opt,S,T,m,n,ans,tot,ss,tt,ee,x,uu[250][250],dd[250][250];
     13 int an[250][250];
     14 char c;
     15 struct lbz
     16 {
     17     int u,v,l,r;
     18 }a[N];
     19 void init()
     20 {
     21     memset(head,0,sizeof(head));
     22     memset(num,0,sizeof(num));
     23     memset(d,0,sizeof(d));
     24     mem(cdu);
     25     mem(rdu);
     26     rep(i,n)
     27         rep(j,m)
     28         {
     29             uu[i][j]=INF;
     30             dd[i][j]=0;
     31         }
     32     flag=ans=ee=eee=0;
     33 }
     34 void add(int u,int v,int c)
     35 {
     36     //printf("%d %d %d
    ",u,v,c);
     37     other[++ee]=ee+1;
     38     e[ee]=v;nex[ee]=head[u];head[u]=ee;len[ee]=c;
     39     other[++ee]=ee-1;
     40     e[ee]=u;nex[ee]=head[v];head[v]=ee;len[ee]=0;
     41 }
     42 int dfs(int x,int flow)
     43 {
     44     int rec,j,p;
     45     if (x==tt) return flow;
     46     rec=0;j=last[x];
     47     while (j!=0)
     48     {
     49         if (len[j]>0 && d[x]==d[e[j]]+1)
     50         {
     51             last[x]=j;
     52             p=dfs(e[j],min(len[j],flow-rec));
     53             len[j]-=p;len[other[j]]+=p;
     54             rec+=p;
     55             if (rec==flow) return rec;
     56         }
     57     j=nex[j];
     58     }
     59     if (d[ss]>tot) return rec;
     60      if (--num[d[x]]==0) d[ss]=tot;
     61      last[x]=head[x];
     62      num[++d[x]]++;
     63      return rec;
     64 }
     65 void deal(int x,int y)
     66 {
     67     if (c=='>')
     68         dd[x][y]=max(dd[x][y],k+1);
     69     if (c=='<')
     70         uu[x][y]=min(uu[x][y],k-1);
     71     if (c=='=')
     72     {
     73         if (k<dd[x][y]||k>uu[x][y])
     74             flag=1;
     75         dd[x][y]=uu[x][y]=k;
     76     }
     77     if (uu[x][y]<dd[x][y])
     78         flag=1;
     79 }
     80 void add1(int u,int v,int l,int r)
     81 {
     82     eee++;
     83     a[eee].u=u;a[eee].v=v;
     84     a[eee].l=l;a[eee].r=r;
     85     rdu[v]+=l;cdu[u]+=l;
     86 }
     87 int main()
     88 {
     89     scanf("%d",&_);
     90     int __=_;
     91     while (_--)
     92     {
     93         if (__!=_-1)    puts("");
     94         scanf("%d%d",&n,&m);
     95         init();
     96         S=2;T=n+m+3;
     97         rep(i,n)
     98         {
     99             scanf("%d",&l);
    100             add1(S,i+2,l,l);
    101         }
    102         rep(i,m)
    103         {    
    104             scanf("%d",&l);
    105             add1(n+i+2,T,l,l);
    106         }
    107         scanf("%d",&opt);
    108         while (opt--)
    109         {
    110             scanf("%d%d %c %d",&x,&y,&c,&k);
    111             if (x==0&&y==0)
    112             {
    113                 rep(i,n)
    114                     rep(j,m)
    115                         deal(i,j);
    116                 continue;
    117             }
    118             if (x==0)
    119             {
    120                 rep(i,n)
    121                     deal(i,y);
    122                 continue;
    123             }
    124             if (y==0)
    125             {
    126                 rep(i,m)
    127                     deal(x,i);
    128                 continue;
    129             }
    130             deal(x,y);
    131         }
    132         if (flag==1)
    133         {
    134             printf("IMPOSSIBLE
    ");
    135             continue;
    136         }
    137         rep(i,n)
    138             rep(j,m)
    139             {
    140                 add1(i+2,j+2+n,dd[i][j],uu[i][j]);
    141             }
    142         ss=S-1;tt=T+1;
    143         rep(i,eee)
    144             add(a[i].u,a[i].v,a[i].r-a[i].l);
    145         for (int i=S;i<=T;i++)
    146         {
    147             add(ss,i,rdu[i]);
    148             add(i,tt,cdu[i]);
    149         }        
    150         add(T,S,INF);
    151 
    152         tot=num[0]=tt;
    153         for (int i=ss;i<=tt;i++)
    154             last[i]=head[i];
    155         while (d[ss]<tot)
    156             ans+=dfs(ss,2147483647);
    157         //printf("%d
    ",ans);
    158         int j=head[ss];
    159         while (j>0)
    160         {
    161             if (len[j]>0)
    162                 flag=1;
    163             j=nex[j];
    164         }
    165         if (flag==1)
    166         {
    167             printf("IMPOSSIBLE
    ");
    168             continue;
    169         }
    170         for (int i=3;i<=2+n;i++)
    171         {
    172             int j=head[i];
    173             while (j>0)
    174             {
    175                 an[i-2][e[j]-n-2]=dd[i-2][e[j]-n-2]+len[other[j]];
    176                 j=nex[j];
    177             }
    178         }
    179         rep(i,n)
    180         {
    181             rep(j,m-1)
    182                 printf("%d ",an[i][j]);
    183             printf("%d
    ",an[i][m]);
    184         }
    185                 
    186     }
    187     return 0;
    188 }
    栗题poj2396

    以下摘自Edelweiss《网络流建模汇总》

    发散思维:
    1. 怎样求无源汇有上下界网络的可行流?
    由于有源汇的网络我们先要转化成无源汇,所以本来就无源汇的网络不用再作特殊处理。
    2. 怎样求无源汇有上下界网络的最大流、最小流?
    一种简易的方法是采用二分的思想,不断通过可行流的存在与否对(t, s)边的上下界U, L进行调整。求最大流时令U = ∞并二分L;求最小流时令L = 0并二分U。道理很简单,因为可行流的取值范围是一段连续的区间,我们只要通过二分找到有解和无解的分界线即可。

    ------------------------------------------------------------------------- 花有重开日,人无再少年
  • 相关阅读:
    ADF中遍历VO中的行数据(Iterator)
    程序中实现两个DataTable的Left Join效果(修改了,网上第二个DataTable为空,所处的异常)
    ArcGIS api for javascript——鼠标悬停时显示信息窗口
    ArcGIS api for javascript——查询,然后单击显示信息窗口
    ArcGIS api for javascript——查询,立刻打开信息窗口
    ArcGIS api for javascript——显示多个查询结果
    ArcGIS api for javascript——用图表显示查询结果
    ArcGIS api for javascript——查询没有地图的数据
    ArcGIS api for javascript——用第二个服务的范围设置地图范围
    ArcGIS api for javascript——显示地图属性
  • 原文地址:https://www.cnblogs.com/lbz007oi/p/6039692.html
Copyright © 2011-2022 走看看