zoukankan      html  css  js  c++  java
  • BZOJ2673 [Wf2011]Chips Challenge 费用流 zkw费用流 网络流

    https://darkbzoj.cf/problem/2673

    有一个芯片,芯片上有N*N(1≤N≤40)个插槽,可以在里面装零件。

    有些插槽不能装零件,有些插槽必须装零件,剩下的插槽随意。

    要求装好之后满足如下两条要求:

    1、第 i 行和第 i 列的零件数目必须一样多(1≤i≤N)。

    2、第 i 行的零件数目不能超过总的零件数目的 A/B(1≤i≤N,0≤A≤B≤1000,B≠0)。

    求最多可以另外放多少个零件(就是除掉必须放的)。如果无解输出impossible。

    zkw费用流就是像跑最大流一样跑费用流,可以并行处理使得稠密图和二分图速度变快(据说)。

    棋盘图依然是把横纵坐标拆成2n个点,每一个棋子可以用其横坐标到纵坐标的一条路表示。

    棋盘上放最多的棋子相当于所有位置放上棋子后去掉最少的棋子,最小费用流处理就是给每一个可以去掉的棋子一个固定费用(1)。

    i行和i列保留零件数目一样多就是从横坐标的i点到纵坐标的i点连一条费用为0流量固定为w的路。 w一定时,每一行每一列保留棋子的数量一定<=w。w上限是n所以我们可以枚举w建n次图跑网络流。

    此时的最大流最小费用就是条件w下可以去掉的棋子数量的最小值(不仅要验证满足题目中的要求2,还要验证最大流=所有可以放棋子的位置的数量,因为保留棋子数量有时候可能小于某行列C的数量)(如果这个w跑最大流最小费用的方案不合法,那么就不存在w的合法条件)。

    这个建n次图的方法有点像noip2017的那道搜索题目 NOIP2017 D2T2宝藏 都是按层次找的想法。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 #define LL long long
     9 const int maxn=60100;
    10 int n,A,B;
    11 char ch[50][50];
    12 int han[50]={},shu[50]={},sum,num,S,T,mx,cnt;
    13 struct nod{
    14     int x,y,next,v,co,rev;
    15 }e[maxn];
    16 int head[150]={},tot=0;
    17 void init(int x,int y,int v,int co){
    18     e[++tot].y=y;e[tot].x=x;e[tot].v=v;e[tot].co=co;e[tot].next=head[x];e[tot].rev=tot+1;head[x]=tot;
    19     e[++tot].y=x;e[tot].x=y;e[tot].v=0;e[tot].co=-co;e[tot].next=head[y];e[tot].rev=tot-1;head[y]=tot;
    20 }
    21 queue<int>q;
    22 int dis[150]={};bool vis[150]={};
    23 bool SPFA(){
    24     memset(dis,63,sizeof(dis));
    25     memset(vis,0,sizeof(vis));
    26     mx=dis[0];
    27     q.push(S);vis[S]=1;dis[S]=0;
    28     while(!q.empty()){
    29         int x=q.front(),y;q.pop();vis[x]=0;
    30         for(int i=head[x];i;i=e[i].next){
    31             y=e[i].y;
    32             if(e[i].v>0&&dis[y]>dis[x]+e[i].co){
    33                 dis[y]=dis[x]+e[i].co;
    34                 if(!vis[y]){
    35                     q.push(y);vis[y]=1;
    36                 }
    37             }
    38         }
    39     }
    40     return dis[T]!=mx;
    41 }
    42 int dfs(int x,int val){
    43     if(x==T){
    44         cnt+=dis[T]*val;
    45         return val;
    46     }
    47     int liu=0,tv,y;vis[x]=1;
    48     for(int i=head[x];i;i=e[i].next){
    49         y=e[i].y;
    50         if(vis[y])continue;
    51         if(e[i].v>0&&dis[y]==dis[x]+e[i].co){
    52             vis[y]=1;
    53             tv=dfs(y,min(val-liu,e[i].v));
    54             liu+=tv;e[i].v-=tv;e[e[i].rev].v+=tv;
    55             if(liu==val)break;
    56         }
    57     }
    58     return liu;
    59 }
    60 int main(){
    61     int C=0;
    62     while(~scanf("%d%d%d",&n,&A,&B)){
    63         if(n==0&&A==0&&B==0)break;
    64         ++C;
    65         memset(han,0,sizeof(han));memset(shu,0,sizeof(shu));
    66         sum=0;cnt=0;S=n*2+1;T=S+1;
    67         int zz=0,ans=-1;
    68         for(int i=0;i<n;i++){
    69             scanf("%s",ch[i]);
    70             for(int j=0;j<n;j++){
    71                 if(ch[i][j]!='/'){
    72                     ++han[i+1];++shu[j+1];++sum;
    73                     if(ch[i][j]=='C')++zz;
    74                 }
    75             }
    76         }
    77         for(int w=0;w<=n;w++){
    78             tot=0;memset(head,0,sizeof(head));
    79             for(int i=1;i<=n;i++){
    80                 init(S,i,han[i],0);
    81                 init(i+n,T,shu[i],0);
    82                 init(i,i+n,w,0);
    83                 for(int j=1;j<=n;j++){
    84                     if(ch[i-1][j-1]=='.')init(i,j+n,1,1);
    85                 }
    86             }int num=0;cnt=0;
    87             while(SPFA()){memset(vis,0,sizeof(vis));num+=dfs(S,sum);}
    88             if(num==sum&&w*B<=(sum-cnt)*A)ans=max(ans,sum-cnt);
    89         }cout<<endl;
    90         if(ans==-1)printf("Case %d: impossible
    ",C);
    91         else printf("Case %d: %d
    ",C,ans-zz);
    92     }
    93     return 0;
    94 }
    View Code

  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8982742.html
Copyright © 2011-2022 走看看