容量有上下界的最大流 poj 2396 pku

 #include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int ulim[250][250],dlim[250][250],f[250][250],h[250],vh[250],din[250],dout[250];
int sour,sink,tsour,tsink,m,n,testcase,tot,flow,augc;
bool flag;
int min(int x,int y)
{
    if(x<y)return x;
    return y;
}
int max(int x,int y)
{
    if(x>y)return x;
    return y;
}
void sap(int x)//DFS实现
{
    if(x==sink)
    {
        flag=true;
        flow+=augc;
        return ;
    }
    int minh=sink-1,tmp=augc,i;
    for(i=1;i<=sink;i++)
         if(f[x][i]>0)
         {
             if(h[x]==h[i]+1)
             {
                 augc=min(f[x][i],augc);
                 sap(i);
                 if(h[sour]>=sink)  return ;
                 if(flag)break;
                 augc=tmp;
             }
             minh=min(minh,h[i]);
         }
    if(flag)
    {
        f[x][i]-=augc;
        f[i][x]+=augc;
    }
    else
    {
        --vh[h[x]];
        if(vh[h[x]]==0)
             h[sour]=sink;
        h[x]=minh+1;
        ++vh[h[x]];
    }
}
int main()
{
    freopen("input.txt","r",stdin);
    scanf("%d",&testcase);
    for(;testcase>0;--testcase)
    {
        scanf("%d%d",&m,&n);
        tsour=m+n+1;tsink=m+n+2;
        sour=m+n+3;sink=m+n+4;
        memset(ulim,0,sizeof(ulim));
        memset(dlim,0,sizeof(dlim));
        for(int i=1;i<=m;i++)
             for(int j=m+1;j<=m+n;j++)
                 ulim[i][j]=0x3f3f3f3f;
        for(int i=1;i<=m;i++)
        {
            int v;
            scanf("%d",&v);
            ulim[tsour][i]=dlim[tsour][i]=v;
        }
        for(int i=m+1;i<=m+n;i++)
        {
            int v;
            scanf("%d",&v);
            ulim[i][tsink]=dlim[i][tsink]=v;
        }
        scanf("%d",&tot);
        for(int k=1;k<=tot;k++)
        {
            int x,y,v;
            char c;
            int x1,x2,y1,y2;
            scanf("%d %d %c %d",&x,&y,&c,&v);
            if(x==0)
            {
                x1=1;x2=m;
            }
            else x1=x2=x;
            if(y==0)
            {
                y1=1+m;y2=m+n;
            }
            else y1=y2=m+y;
            for(int i=x1;i<=x2;i++)
                  for(int j=y1;j<=y2;j++)
                      if(c=='<')
                          ulim[i][j]=min(ulim[i][j],v-1);
                      else if(c=='>')
                          dlim[i][j]=max(dlim[i][j],v+1);
                      else if(c=='=')
                      {
                          ulim[i][j]=min(ulim[i][j],v);
                          dlim[i][j]=max(dlim[i][j],v);
                      }
        }
        ulim[tsink][tsour]=0x3f3f3f3f;
        memset(din,0,tsink+1<<2);
        memset(dout,0,tsink+1<<2);
        memset(f,0,sizeof(f));
        flag=true;
        for(int i=1;i<=tsink && flag;++i)
              for(int j=1;j<=tsink && flag;++j)
                  if(dlim[i][j]>ulim[i][j])
                       flag=false;
      if (!flag)
        {
            printf("IMPOSSIBLE/n/n");
            continue;
        }
        for (int i=1;i<=tsink;++i)
             for (int j=1;j<=tsink;++j)
             {
                din[j]+=dlim[i][j];
                dout[i]+=dlim[i][j];
             }
        for(int i=1;i<=tsink;++i)
              for(int j=1;j<=tsink;++j)
                  f[i][j]=ulim[i][j]-dlim[i][j];
        for(int i=1;i<=tsink;i++)
             if(din[i]>=dout[i])
                 f[sour][i]=din[i]-dout[i];
             else  f[i][sink]=dout[i]-din[i];
        memset(h,0,sink+1<<2);
        memset(vh,0,sink+1<<2);
        vh[0]=sink;
        flow=0;
        while(h[sour]<sink)
        {
            flag=false;
            augc=0x3f3f3f3f;
            sap(sour);
        }
        flag=true;
        for(int i=1;i<=sink&&flag;i++)
            if(f[sour][i]>0)
               flag=false;
        if(!flag)
        {
            printf("IMPOSSIBLE/n/n");
            continue;
        }
        for(int i=1;i<=m;i++)
             for(int j=m+1;j<=m+n;j++)
             {
                 printf("%d",ulim[i][j]-f[i][j]);
                 if(j!=m+n)
                     printf(" ");
                 else printf("/n");
             }
        printf("/n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值