zoukankan      html  css  js  c++  java
  • [BZOJ1458] 士兵占领

    1458: 士兵占领

    Time Limit: 10 Sec  Memory Limit: 64 MB

    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
     
     

    SOLUTION

    这题就是如果一个士兵所在的行和列都需要士兵,那么这个士兵就可以做出两个贡献,在刚开始的时候统计最差的士兵数量之和,也就是需要就加上,然后行和列建边,跑一边最大流,找出最多的可以做出两个贡献的士兵,然后用sum减去即可

    找最小的值可以考虑最大流再相减

      1 #include<cmath>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<iostream>
      7 #include<algorithm>
      8 # define INF 100000
      9 using namespace std;
     10 int n,m,lim;
     11 int hang[110],lie[110];
     12 bool pan[110][110];
     13 int S,T,SUM;
     14 struct node{
     15     int u,v,w,nxt;
     16 }g[20010];
     17 int adj[20010],e;
     18 void add(int u,int v,int w){
     19     g[e].v=v; g[e].u=u; g[e].w=w;
     20     g[e].nxt=adj[u]; adj[u]=e++;
     21 }
     22 bool Jud(){
     23     bool ok=1;
     24     for(int i=1;i<=n;i++){
     25         int he=0;
     26         for(int j=1;j<=m;j++){
     27             if(!pan[i][j]) he++;
     28         }
     29         if(he<hang[i]){ok=0;break;}
     30     }
     31     if(ok){
     32         for(int j=1;j<=m;j++){
     33             int he=0;
     34             for(int i=1;i<=n;i++){
     35                 if(!pan[i][j]) he++;
     36             }
     37             if(he<lie[j]){ok=0;break;}
     38         }
     39     }
     40     return ok;
     41 }
     42 int dep[310];
     43 bool BFS(){
     44     memset(dep,0,sizeof(dep));
     45     queue<int> q;
     46     dep[S]=1; q.push(S);
     47     int k;
     48     while(!q.empty()){
     49         k=q.front(); q.pop();
     50         for(int i=adj[k];i!=-1;i=g[i].nxt){
     51             int v=g[i].v;
     52             if(g[i].w && !dep[v]){
     53                 dep[v]=dep[k]+1;
     54                 if(v==T) return 1;
     55                 q.push(v);
     56             }
     57         }
     58     }
     59     return 0;
     60 }
     61 int dfs(int x,int fw){
     62     if(x==T) return fw;
     63     int tmp=fw,k;
     64     for(int i=adj[x];i!=-1;i=g[i].nxt){
     65         int v=g[i].v;
     66         if(g[i].w && tmp && dep[v]==dep[x]+1){
     67             k = dfs(v,min(g[i].w,tmp));
     68             if(!k){
     69                 dep[v]=0;
     70                 continue;
     71             }
     72             g[i].w-=k; g[i^1].w+=k; tmp-=k;
     73         }
     74     }
     75     return fw-tmp;
     76 }
     77 void work(){
     78     memset(adj,-1,sizeof(adj));
     79     S=0; T=110;
     80     for(int i=1;i<=n;i++) add(S,i,hang[i]), add(i,S,0);
     81     int jia=101;
     82     for(int j=1;j<=m;j++) add(j+jia,T,lie[j]), add(T,j+jia,0);
     83     for(int i=1;i<=n;i++){
     84         for(int j=1;j<=m;j++){
     85             if(pan[i][j]) continue;
     86             add(i,j+jia,1); add(j+jia,i,0);
     87         }
     88     }
     89     int he=0,tan;
     90     while(BFS()){
     91         while(tan=dfs(S,INF)) he+=tan;
     92     }
     93     printf("%d",SUM-he);
     94 }
     95 int main(){
     96     //freopen("a.in","r",stdin);
     97     //freopen("a.out","w",stdout);
     98     scanf("%d%d%d",&n,&m,&lim);
     99     for(int i=1;i<=n;i++) scanf("%d",&hang[i]), SUM+=hang[i];
    100     for(int i=1;i<=m;i++) scanf("%d",&lie[i]),  SUM+=lie[i];
    101     int x,y;
    102     for(int i=1;i<=lim;i++){
    103         scanf("%d%d",&x,&y);
    104         pan[x][y]=1;
    105     }
    106     S=0; T=110;
    107     bool ok=Jud();
    108     if(!ok){
    109         printf("JIONG
    ");
    110         return 0;
    111     }
    112     work();
    113     return 0;
    114 }
  • 相关阅读:
    每周学算法/读英文/知识点心得分享 1.28
    ARTS 1.21
    ARTS 1.14
    ARTS 1.7
    ARTS 12.31
    ARTS 12.24
    Leetcode : Median of Two Sorted Arrays
    我是怎样改善遗留系统的
    《大话重构》免费送书活动开始啦
    我的新书终于要出来啦
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7265856.html
Copyright © 2011-2022 走看看