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

  • 相关阅读:
    MySQL数据模型
    Spring循环依赖
    @Autowired和@Resource区别
    Kafka概念
    阻塞队列
    线程池原理
    Spring AOP
    JVM 史上最最最完整深入解析(12000 字噢)
    Dubbo配置信息
    友情链接
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8982742.html
Copyright © 2011-2022 走看看