• 洛谷P4311 士兵占领


    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    4
    

    说明

    M, N <= 100, 0 <= K <= M * N Local

    Solution

    做了做思想准备还是写一下这个题的Solution。

    正难则反的思想。

    我们发现让使用最少个数的士兵占领整个棋盘,那么如果我们放满了整个棋盘之后,我们判断拿走那些仍然能够满足占领整个棋盘这个条件。我们可以预处理出每一行每一列最多能拿走多少个,然后对于没有放置障碍的格子,就表示这个地方可能能删去一个士兵,就用所在的行连向所在的列,最后一遍最大流。

    那么判断是否合法呢?跑一遍连接源汇的边就可以了,查看一下是不是跑满流了。

    Code

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define re register
    #define inf 400000000
    #define MAXN 501
    #define MAXM 100001
    using namespace std;
    int n,s,q,dis[2000011],t,cur[200051],m,k,b[201][201],tot;
    int l[201],h[201],lx[201],hx[201];
    struct po
    {
        int nxt,to,w;
    }edge[MAXM];
    int head[MAXN],dep[MAXN],num=-1;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void add_edge(int from,int to,int w)
    {
        edge[++num].nxt=head[from];
        edge[num].to=to;
        edge[num].w=w;
        head[from]=num;
    }
    inline void add(int from,int to,int w)
    {
        add_edge(from,to,w);
        add_edge(to,from,0);
    }
    inline bool bfs()
    {
        memset(dep,0,sizeof(dep));
        queue<int> q;
        while(!q.empty())
        q.pop();
        q.push(s);
        dep[s]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(re int i=head[u];i!=-1;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dep[v]==0&&edge[i].w>0)
                {
                    dep[v]=dep[u]+1;
                    if(v==t)
                    return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    inline int dfs(int u,int dis)
    {
        if(u==t)
        return dis;
        int diss=0;
        for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].w!=0&&dep[v]==dep[u]+1)
            {
                int check=dfs(v,min(dis,edge[i].w));
                if(check>0)
                {
                    dis-=check;
                    diss+=check;
                    edge[i].w-=check;
                    edge[i^1].w+=check;
                    if(dis==0) break;
                }
            }
        }
        return diss;
    }
    inline int dinic()
    {
        int ans=0;
        while(bfs())
        {
            for(re int i=0;i<=t;i++)
            cur[i]=head[i];
            while(int d=dfs(s,inf))
            ans+=d;
        }
        return ans;
    }
    int main() 
    {
        memset(head,-1,sizeof(head));
    	n=read();m=read();k=read();
    	s=0;t=n+m+1;
        for(re int i=1;i<=n;i++)
            l[i]=read();
        for(re int i=1;i<=m;i++)
            h[i]=read();
        for(re int i=1;i<=k;i++){
            int x=read(),y=read();
            b[x][y]=1;lx[x]++;hx[y]++;
        }
        for(re int i=1;i<=n;i++)
        add(s,i,m-lx[i]-l[i]);
        for(re int i=1;i<=m;i++)
        add(i+n,t,n-hx[i]-h[i]);
        for(re int i=1;i<=n;i++)
            for(re int j=1;j<=m;j++){
                if(!b[i][j]) tot++,add(i,j+n,1);
            }
        int d=dinic();
        for(re int i=head[s];i!=-1;i=edge[i].nxt)
            if(edge[i].w!=0){
                cout<<"JIONG";
                return 0;
            }
        for(re int i=head[t];i!=-1;i=edge[i].nxt){
            if(edge[i^1].w!=0){
                cout<<"JIONG";
                return 0;
            }
        }
        cout<<tot-d;
        return 0;
    }
    
    
  • 相关阅读:
    POJ3320 Jessica's Reading Problem
    POJ3320 Jessica's Reading Problem
    CodeForces 813B The Golden Age
    CodeForces 813B The Golden Age
    An impassioned circulation of affection CodeForces
    An impassioned circulation of affection CodeForces
    Codeforces Round #444 (Div. 2) B. Cubes for Masha
    2013=7=21 进制转换
    2013=7=15
    2013=7=14
  • 原文地址:https://www.cnblogs.com/victorique/p/9036617.html
Copyright © 2020-2023  润新知