zoukankan      html  css  js  c++  java
  • poj 2396 Budget

    一个m行n列的矩阵,给出每行每列中元素的和,以及对一些格子的大小限制,求一个可行方案,输出矩阵。

    大小限制形如:严格大于i,严格小于i,等于i。

    1<=m<=200.1<=n<=20.

    有源汇上下界可行流。

    将每一行作为一个点,每一列作为一个点。

    源点向每个行点连一条上下界均为该行和的边。

    每个列点向汇点连一条上下界均为该列和的边。

    每个行点向各列点连一条上下界为该行该列对应点的上下限的边。

    然后做一遍有源汇上下界可行流就好了。

    (汇点向源点连一条上界为正无穷下界为0的边,就转成无源汇上下界可行流啦!

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int dian=305;
      8 const int bian=10005;
      9 const int INF=0x3f3f3f3f;
     10 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian];
     11 int sx[205][25],xx[205][25],bh[205][25],in[dian],out[dian];
     12 int n,m,aa,bb,cc,tot,num,flag,summ;
     13 int S,T,SS,TT;
     14 char la[10];
     15 void add(int a,int b,int c,int d){
     16     tot++;ver[tot]=b;val[tot]=d-c;nxt[tot]=h[a];h[a]=tot;
     17     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
     18     in[b]+=c;
     19     out[a]+=c;
     20 }
     21 bool tell(){
     22     memset(ch,-1,sizeof(ch));
     23     queue<int>q;
     24     q.push(S);
     25     ch[S]=0;
     26     while(!q.empty()){
     27         int t=q.front();
     28         q.pop();
     29         for(int i=h[t];i;i=nxt[i])
     30             if(ch[ver[i]]==-1&&val[i]){
     31                 ch[ver[i]]=ch[t]+1;
     32                 q.push(ver[i]);
     33             }
     34     }
     35     return ch[T]!=-1;
     36 }
     37 int zeng(int a,int b){
     38     if(a==T)
     39         return b;
     40     int r=0;
     41     for(int i=cr[a];i&&b>r;i=nxt[i])
     42         if(ch[ver[i]]==ch[a]+1&&val[i]){
     43             int t=zeng(ver[i],min(b-r,val[i]));
     44             val[i]-=t,r+=t,val[i^1]+=t;
     45             if(val[i])
     46                 cr[a]=i;
     47         }
     48     if(!r)
     49         ch[a]=-1;
     50     return r;
     51 }
     52 int dinic(){
     53     int r=0,t;
     54     while(tell()){
     55         for(int i=1;i<=n+m+4;i++)
     56             cr[i]=h[i];
     57         while(t=zeng(S,INF))
     58             r+=t;
     59     }
     60     return r;
     61 }
     62 int main(){
     63     int cas;
     64     scanf("%d",&cas);
     65     while(cas--){
     66         memset(h,0,sizeof(h));
     67         memset(nxt,0,sizeof(nxt));
     68         memset(sx,0x3f,sizeof(sx));
     69         memset(xx,0,sizeof(xx));
     70         memset(in,0,sizeof(in));
     71         memset(out,0,sizeof(out));
     72         tot=1;
     73         summ=0;
     74         scanf("%d%d",&n,&m);
     75         SS=n+m+1,TT=n+m+2,S=n+m+3,T=n+m+4;
     76         for(int i=1;i<=n;i++){
     77             scanf("%d",&aa);
     78             add(SS,i,aa,aa);
     79         }
     80         for(int i=1;i<=m;i++){
     81             scanf("%d",&aa);
     82             add(n+i,TT,aa,aa);
     83         }
     84         scanf("%d",&num);
     85         while(num--){
     86             scanf("%d%d%s%d",&aa,&bb,la,&cc);
     87             if(!aa&&!bb){
     88                 for(int i=1;i<=n;i++)
     89                     for(int j=1;j<=m;j++){
     90                         if(la[0]=='<')
     91                             sx[i][j]=min(sx[i][j],cc-1);
     92                         else if(la[0]=='>')
     93                             xx[i][j]=max(xx[i][j],cc+1);
     94                         else{
     95                             sx[i][j]=min(sx[i][j],cc);
     96                             xx[i][j]=max(xx[i][j],cc);
     97                         }
     98                     }
     99             }
    100             else if(!aa){
    101                 for(int i=1;i<=n;i++){
    102                     if(la[0]=='<')
    103                         sx[i][bb]=min(sx[i][bb],cc-1);
    104                     else if(la[0]=='>')
    105                         xx[i][bb]=max(xx[i][bb],cc+1);
    106                     else{
    107                         sx[i][bb]=min(sx[i][bb],cc);
    108                         xx[i][bb]=max(xx[i][bb],cc);
    109                     }
    110                 }
    111             }
    112             else if(!bb){
    113                 for(int i=1;i<=m;i++){
    114                     if(la[0]=='<')
    115                         sx[aa][i]=min(sx[aa][i],cc-1);
    116                     else if(la[0]=='>')
    117                         xx[aa][i]=max(xx[aa][i],cc+1);
    118                     else{
    119                         sx[aa][i]=min(sx[aa][i],cc);
    120                         xx[aa][i]=max(xx[aa][i],cc);
    121                     }
    122                 }
    123                 for(int i=1;i<=n;i++){
    124                     if(la[0]=='<')
    125                         sx[i][bb]=min(sx[i][bb],cc-1);
    126                     else if(la[0]=='>')
    127                         xx[i][bb]=max(xx[i][bb],cc+1);
    128                     else{
    129                         sx[i][bb]=min(sx[i][bb],cc);
    130                         xx[i][bb]=max(xx[i][bb],cc);
    131                     }
    132                 }
    133             }
    134             else{
    135                 if(la[0]=='<')
    136                     sx[aa][bb]=min(sx[aa][bb],cc-1);
    137                 else if(la[0]=='>')
    138                     xx[aa][bb]=max(xx[aa][bb],cc+1);
    139                 else{
    140                     sx[aa][bb]=min(sx[aa][bb],cc);
    141                     xx[aa][bb]=max(xx[aa][bb],cc);
    142                 }
    143             }
    144         }
    145         flag=0;
    146         for(int i=1;i<=n;i++){
    147             for(int j=1;j<=m;j++){
    148                 if(sx[i][j]>=xx[i][j]){
    149                     bh[i][j]=tot+1;
    150                     add(i,n+j,xx[i][j],sx[i][j]);
    151                 }
    152                 else{
    153                     flag=1;
    154                     break;
    155                 }
    156             }
    157             if(flag)
    158                 break;
    159         }
    160         if(flag){
    161             puts("IMPOSSIBLE");
    162             puts("");
    163             continue;
    164         }
    165         add(TT,SS,0,INF);
    166         for(int i=1;i<=TT;i++){
    167             if(in[i]-out[i]>0)
    168                 add(S,i,0,in[i]-out[i]);
    169             else if(out[i]-in[i]>0){
    170                 add(i,T,0,out[i]-in[i]);
    171                 summ=summ+out[i]-in[i];
    172             }
    173         }
    174         if(dinic()!=summ){
    175             puts("IMPOSSIBLE");
    176             puts("");
    177             continue;
    178         }
    179         for(int i=1;i<=n;i++){
    180             for(int j=1;j<=m;j++)
    181                 printf("%d ",xx[i][j]+val[bh[i][j]^1]);
    182             puts("");
    183         }
    184         puts("");
    185     }
    186     return 0;
    187 }

    注意:

    一个格子可能有多重限制,上限取min下限取max。

    上限可能小于下限要判掉。

    每组数据输出间有空行(不加也没事?)。

    如果wa了就再读一遍建图,不行就再读一遍。

  • 相关阅读:
    Oracle 操作数据库(增删改语句)
    web----框架基础
    js----DOM对象
    易错之for循环
    python调用修改变量新方法
    js----基础
    web----Twisted
    web----Socket
    python----面向对象(2)
    python----面向对象
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6266060.html
Copyright © 2011-2022 走看看