zoukankan      html  css  js  c++  java
  • bzoj1458: 士兵占领

    1458: 士兵占领

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 920  Solved: 518
    [Submit][Status][Discuss]

    Description

    有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。

    Input

    第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数。 第二行有M个数表示Li。 第三行有N个数表示Ci。 接下来有K行,每行两个数X, Y表示(X, Y)这个格子是障碍。

    Output

    输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出”JIONG!” (不含引号)

    Sample Input

    4 4 4
    1 1 1 1
    0 1 0 3
    1 4
    2 2
    3 3
    4 3

    Sample Output

    4
    数据范围
    M, N <= 100, 0 <= K <= M * N
     
    题解by黄学长:

    此题的思路是先放满棋盘,然后考虑最多可以删多少个。。。

    某一行和某一列的可以放的格子数小于需求就直接jiong掉
    然后从源向每一行连边,流量为可以放的格子数 - 需求的格子数(也就是可以删多少格子)
    从每一列向汇,同上.
    从每一个非障碍的格子的行向列连边流量为1
    跑一遍最大流即可ans=可放格子数-maxflow

     1 #include<bits/stdc++.h>
     2 #define rep(i,l,r) for(int i=l;i<=r;++i)
     3 const int N=102333,inf=2147483647;
     4 using namespace std;
     5 int head[N],dis[N],tot=1,n,m,K,ans,x,y,l[N],l1[N],p[N],p1[N],T;
     6 bool mp[123][123];
     7 struct zs{
     8     int to,next,w;
     9 }e[N];
    10 inline bool bfs(){
    11      for(int i=0;i<=T;i++) dis[i]=-1; queue<int>q; q.push(0); dis[0]=0;
    12      while(!q.empty()) {
    13           int x=q.front(); q.pop();
    14           for(int k=head[x];k;k=e[k].next) 
    15              if(dis[e[k].to]<0 && e[k].w>0) {
    16                    dis[e[k].to]=dis[x]+1; q.push(e[k].to);
    17              }
    18      }
    19      if(dis[T]>0) return 1;else return 0;
    20 }
    21 int find(int x,int low){
    22      if(x==T) return low;
    23      int delta=low,now;
    24      for(int k=head[x];k;k=e[k].next) 
    25        if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 
    26            now=find(e[k].to,min(e[k].w,delta));
    27            e[k].w-=now; e[k^1].w+=now;   delta-=now;
    28            if(!delta) return low;
    29         } 
    30      dis[x]=-1;
    31      return low-delta;
    32 }
    33 inline void ins(int u,int v,int w){
    34     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
    35 }
    36 inline void insert(int u,int v,int w){
    37     ins(u,v,w); ins(v,u,0);
    38 }
    39 int main(){
    40     scanf("%d%d%d",&n,&m,&K);
    41     ans=m*n;
    42     T=1+n+m;
    43     rep(i,1,n) scanf("%d",&l[i]);
    44     rep(i,1,m) scanf("%d",&l1[i]);
    45     rep(i,1,K) scanf("%d%d",&x,&y),mp[x][y]=1,p[x]++,p1[y]++,--ans;
    46     rep(i,1,n) rep(j,1,m) if(!mp[i][j]) insert(i,j+n,1);
    47     rep(i,1,n) insert(0,i,m-p[i]-l[i]);
    48     rep(i,1,m) insert(i+n,T,n-p1[i]-l1[i]);
    49     while(bfs()) ans-=find(0,inf);
    50     for(int k=head[0];k;k=e[k].next) if(e[k].w){puts("JIONG!"); return 0;}
    51     printf("%d
    ",ans);
    52 }
    View Code
  • 相关阅读:
    BZOJ1070: [SCOI2007]修车(最小费用最大流,思维)
    CF892D—Gluttony(思维,好题)
    BZOJ1005--[HNOI2008]明明的烦恼(树的prufer编码)
    HDU–5988-Coding Contest(最小费用最大流变形)
    【转】HDU 6194 string string string (2017沈阳网赛-后缀数组)
    【转】Codeforces Round #406 (Div. 1) B. Legacy 线段树建图&&最短路
    HDU6513/CCPC2017--A Secret(KMP)
    8.19-星期五
    CodeForces–830B--模拟,树状数组||线段树
    js实现360度图片旋转
  • 原文地址:https://www.cnblogs.com/Bloodline/p/5886471.html
Copyright © 2011-2022 走看看