• 有上下界的网络流


    以下摘自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。道理很简单,因为可行流的取值范围是一段连续的区间,我们只要通过二分找到有解和无解的分界线即可。

    ------------------------------------------------------------------------- 花有重开日,人无再少年
  • 相关阅读:
    利用wikipedia 的API实现对其内容的查询
    Android 无标题 全屏设置
    anroid中ScrollView嵌套ListView
    ListView的不同item加载不同Layout,listviewlayout
    ListView缓存机制
    演化理解 Android 异步加载图片
    【自定义控件】自定义属性
    【自定义控件】组合控件
    【自定义控件】的基本步骤
    ContentResolver如何获取本地媒体文件
  • 原文地址:https://www.cnblogs.com/lbz007oi/p/6039692.html
Copyright © 2020-2023  润新知