zoukankan      html  css  js  c++  java
  • 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('
    ');
     99         printf("Matrix %d
    ",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('
    ');
    105         }
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    针对数据库开发人员的性能调优小提示
    Oracle EBS 12 目录结构
    程序集反射
    DataTable.Select() 返回DataTable结果
    有趣的23中设计模式
    『原创』用C++开发WM应用系列(5)——接触ListBox控件
    『原创』用C++开发WM应用系列(1)——"Hello World" Pro!(上)
    【参考】在PPC上面检查文件MD5
    用C++开发WM应用系列文章索引
    『原创』用C++开发WM应用系列(1)——"Hello World" Pro!(下)
  • 原文地址:https://www.cnblogs.com/WABoss/p/5726542.html
Copyright © 2011-2022 走看看