UVa11082 Matrix Decompressing(最小费用最大流)

题目大概有一个n*m的矩阵,已知各行所有数的和的前缀和和各列所有数的和的前缀和,且矩阵各个数都在1到20的范围内,求该矩阵的一个可能的情况。

 

POJ2396的弱化版本吧。。建图的关键在于:

  • 把行、列看成点,各单元看成边

这个建图感觉非常巧。。

 

各个单元有下界限制。。这个我可不想再写带下界的最大流。。

想了下,发现可以用最小费用最大流求解:通过放大边的费用,使得这条边成为一条必须会被经过的边。

简单来说就是各单元代表的边拆成两条,一条容量1费用-1,另外一条容量19费用0。这样跑MCMF,显然为了让费用最小,所有费用-1的边必然会经过,这样就保证了各个单元的值至少为1。

(其实有个更简单的方法就是所有单元格都同时减去1。。)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define MAXN 44
  7 #define MAXM 88*88
  8 #define INF (1<<30)
  9 
 10 struct Edge{
 11     int v,cap,cost,next;
 12 }edge[MAXM];
 13 int vs,vt,NV,NE,head[MAXN];
 14 void addEdge(int u,int v,int cap,int cost){
 15     edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
 16     edge[NE].next=head[u]; head[u]=NE++;
 17     edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
 18     edge[NE].next=head[v]; head[v]=NE++;
 19 }
 20 
 21 int d[MAXN],pre[MAXN];
 22 bool inque[MAXN];
 23 bool SPFA(){
 24     for(int i=0; i<NV; ++i){
 25         d[i]=INF; inque[i]=0;
 26     }
 27     d[vs]=0; inque[vs]=1;
 28     queue<int> que;
 29     que.push(vs);
 30     while(!que.empty()){
 31         int u=que.front(); que.pop();
 32         for(int i=head[u]; i!=-1; i=edge[i].next){
 33             int v=edge[i].v;
 34             if(edge[i].cap && d[v]>d[u]+edge[i].cost){
 35                 d[v]=d[u]+edge[i].cost;
 36                 pre[v]=i;
 37                 if(!inque[v]){
 38                     inque[v]=1;
 39                     que.push(v);
 40                 }
 41             }
 42         }
 43         inque[u]=0;
 44     }
 45     return d[vt]!=INF;
 46 }
 47 int mxflow;
 48 int MCMF(){
 49     mxflow=0;
 50     int res=0;
 51     while(SPFA()){
 52         int flow=INF,cost=0;
 53         for(int u=vt; u!=vs; u=edge[pre[u]^1].v){
 54             flow=min(flow,edge[pre[u]].cap);
 55         }
 56         mxflow+=flow;
 57         for(int u=vt; u!=vs; u=edge[pre[u]^1].v){
 58             edge[pre[u]].cap-=flow;
 59             edge[pre[u]^1].cap+=flow;
 60             cost+=edge[pre[u]].cost;
 61         }
 62         res+=cost*flow;
 63     }
 64     return res;
 65 }
 66 
 67 int row[22],col[22],ans[22][22];
 68 int main(){
 69     int t,n,m;
 70     scanf("%d",&t);
 71     for(int cse=1; cse<=t; ++cse){
 72         scanf("%d%d",&n,&m);
 73         vs=0; vt=n+m+1; NV=vt+1; NE=0;
 74         memset(head,-1,sizeof(head));
 75         for(int i=1; i<=n; ++i){
 76             scanf("%d",row+i);
 77             addEdge(vs,i,row[i]-row[i-1],0);
 78         }
 79         for(int i=1; i<=m; ++i){
 80             scanf("%d",col+i);
 81             addEdge(i+n,vt,col[i]-col[i-1],0);
 82         }
 83         for(int i=1; i<=n; ++i){
 84             for(int j=1; j<=m; ++j){
 85                 addEdge(i,j+n,1,-1);
 86                 addEdge(i,j+n,19,0);
 87             }
 88         }
 89         MCMF();
 90         memset(ans,0,sizeof(ans));
 91         for(int u=1; u<=n; ++u){
 92             for(int i=head[u]; i!=-1; i=edge[i].next){
 93                 if(i&1) continue;
 94                 int v=edge[i].v-n;
 95                 ans[u][v]+=edge[i^1].cap;
 96             }
 97         }
 98         if(cse!=1) putchar('\n');
 99         printf("Matrix %d\n",cse);
100         for(int i=1; i<=n; ++i){
101             for(int j=1; j<=m; ++j){
102                 printf("%d ",ans[i][j]);
103             }
104             putchar('\n');
105         }
106     }
107     return 0;
108 }

 

posted @ 2016-08-01 17:17  WABoss  阅读(315)  评论(0编辑  收藏  举报