zoukankan      html  css  js  c++  java
  • 土兵占领:二分答案,最大流

    Description

    有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些土兵,一个格子里最多可以放置一个土兵,障碍格里不能放置土兵。

    我们称这些土兵占领了整个棋盘当满足第i行至少放置了Li个土兵, 第j列至少放置了Cj个土兵。

    现在你的任务是要求使用最少个数的土兵来占领整个棋盘。

    n,m<=100

    把“士”替换成“土”我是故意的不要告诉我啊啊啊啊啊

    来自网络流专题,默认颓了标签。

    因为直接做死掉了所以要二分答案。

    关键在于怎么建图。

    NC说他没什么印象因为这道题切的太快了,然而我想了好半天。。。。

    一些失败的想法:

    把土兵放在左部,行列要求都放在右部,跑最大流。。。不行。。。每个兵会有2的流出很不好控制。。

    把左右反过来也还是一样的。。。

    所以我们考虑怎么把那个讨厌的2干掉。

    那么如果关于行的我们设置为入边,关于列的设置为出边,这样就没有2了。

    然后我们把行要求作为左部点,列要求作为中间点,土兵作为中间点。

    这样的话必须保证右部满流,所以求解变成了检查,问题可以二分答案,而二分整个图的入流就是答案。

    如果放满了土兵还达不到要求就是无解啦。。

    但是我们可以发现,左边的行要求点是有最小限流的,流量不够就相当于没有满足要求。

    所以有点像上下界网络流?但是我不会。

    于是我开始自己YY,想到了再开一个新的超级源点,然后从它往左部点连等量于限制的边。

    再把它与普通源点连(mid-总左部点要求)的边。

    普通源点与左部点连inf的边,这样就满足了所有的要求。

    其实就是上下界网络流的思想啦。。。

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int m,n,k,x[111][111],cn,L[111],R[111],ord[111][111],Lord[111],Rord[111];
     5 int fir[16666],l[66666],to[66666],v[66666],cnt,dep[16666],q[16666];
     6 void link(int a,int b,int V){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;v[cnt]=V;}
     7 bool bfs(){
     8     for(int i=1;i<=cn;++i)dep[i]=1234567890;
     9     for(int h=1,t=1;h<=t;++h)for(int i=fir[q[h]];i;i=l[i])if(v[i]&&dep[to[i]]>dep[q[h]]+1)
    10         dep[to[i]]=dep[q[h]]+1,q[++t]=to[i];
    11     return dep[cn]!=1234567890;
    12 }
    13 int dfs(int p,int flow){
    14     if(p==cn)return flow;int res=flow;
    15     for(int i=fir[p];i;i=l[i])if(v[i]&&dep[to[i]]==dep[p]+1){
    16         int r=dfs(to[i],min(flow,v[i]));
    17         v[i]-=r;v[i^1]+=r;flow-=r;
    18     }
    19     return res-flow;
    20 }
    21 bool chk(int mid){int max_flow=0,goal=0;
    22     for(int i=0;i<=cn;++i)fir[i]=0;cnt=1;
    23     for(int i=1;i<=n;++i)link(0,Lord[i],L[i]),link(Lord[i],0,0),mid-=L[i];
    24     if(mid<0)return false;
    25     for(int i=1;i<=m;++i)link(Rord[i],cn,R[i]),link(cn,Rord[i],0),goal+=R[i];
    26     for(int i=1;i<=n;++i)link(cn-1,Lord[i],1234567890),link(Lord[i],cn-1,0);
    27     link(0,cn-1,mid);link(cn-1,0,0);
    28     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(x[i][j]!=-1)
    29         link(Lord[i],x[i][j],1),link(x[i][j],Lord[i],0),
    30         link(x[i][j],Rord[j],1),link(Rord[j],x[i][j],0);
    31     while(bfs())max_flow+=dfs(0,1234567890);
    32     return max_flow==goal;
    33 }
    34 int main(){
    35     scanf("%d%d%d",&n,&m,&k);
    36     for(int i=1;i<=n;++i)scanf("%d",&L[i]),Lord[i]=++cn;
    37     for(int i=1;i<=m;++i)scanf("%d",&R[i]),Rord[i]=++cn;
    38     for(int i=1,a,b;i<=k;++i)scanf("%d%d",&a,&b),x[a][b]=-1;
    39     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(x[i][j]!=-1)ord[i][j]=++cn;
    40     cn+=2;
    41     int l=0,r=n*m;
    42     while(l<r-1)if(chk(l+r>>1))r=l+r>>1;else l=(l+r>>1)+1;
    43     if(chk(l))printf("%d
    ",l);else if(chk(r))printf("%d
    ",r);else puts("JIONG!");
    44 }
    View Code
  • 相关阅读:
    Mysql配置文件解析
    Mysql的视图
    Setup和 Hold
    洛谷 P2257
    洛谷 P3455
    洛谷 P1447
    洛谷 P1155
    洛谷 P1262
    洛谷 P4180
    洛谷 P5540
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11579851.html
Copyright © 2011-2022 走看看