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了就再读一遍建图,不行就再读一遍。

posted @ 2017-01-09 17:40  dugudashen  阅读(201)  评论(0编辑  收藏  举报