zoukankan      html  css  js  c++  java
  • 1458: 士兵占领[最大流]

    1458: 士兵占领

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1044  Solved: 598
    [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

    HINT

     

    Source

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define EF if(ch==EOF) return x;
    using namespace std;
    const int N=205;
    const int M=1e5+5;
    const int inf=2e9;
    struct edge{int v,next,cap;}e[M<<1];int tot=1,head[N];
    int n,m,ans,K,S,T,L[N],C[N],G[N],H[N],dis[N<<1],q[M];
    short mp[N][N];
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;EF;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void add(int x,int y,int z){
        e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
        e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
    }
    bool bfs(){
        memset(dis,-1,sizeof dis);
        int h=0,t=1;q[t]=S;dis[S]=0;
        while(h!=t){
            int x=q[++h];
            for(int i=head[x];i;i=e[i].next){
                if(e[i].cap&&dis[e[i].v]==-1){
                    dis[e[i].v]=dis[x]+1;
                    if(e[i].v==T) return 1;
                    q[++t]=e[i].v;
                }
            } 
        }
        return 0;
    }
    int dfs(int x,int f){
        if(x==T) return f;
        int used=0,t;
        for(int i=head[x];i;i=e[i].next){
            if(e[i].cap&&dis[e[i].v]==dis[x]+1){
                t=dfs(e[i].v,min(e[i].cap,f));
                e[i].cap-=t;e[i^1].cap+=t;
                used+=t;f-=t;
                if(!f) return used;
            }
        }
        if(!used) dis[x]=-1;
        return used;
    }
    void dinic(){
        ans=0;
        while(bfs()) ans+=dfs(S,inf);
    }
    void work(){
        n=read();m=read();K=read();S=0,T=n+m+1;
        for(int i=1;i<=n;i++) L[i]=read();
        for(int i=1;i<=m;i++) C[i]=read();
        for(int i=1,x,y;i<=K;i++){
            x=read(),y=read(),G[x]++,H[y]++,mp[x][y]=1;
            if(n-H[y]<C[y]||m-G[x]<L[x]){
                printf("JIONG!");return ;
            }
        } 
        for(int i=1;i<=n;i++) add(S,i,L[i]);
        for(int i=1;i<=m;i++) add(i+n,T,C[i]);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(!mp[i][j]){
                    add(i,j+n,1);
                }
            }
        }
        dinic();
        for(int i=head[S];i;i=e[i].next) ans+=e[i].cap;
        for(int i=head[T];i;i=e[i].next) ans+=e[i^1].cap;
        printf("%d",ans);
    }
    int main(){
        work();
        return 0;
    }
  • 相关阅读:
    Python_day1
    12/04
    Linux基础笔记
    八:动态规划-未名湖边的烦恼
    七:动态规划-数字三角形
    六:大数运算-减法运算
    五:大数运算-加法运算
    四:大数运算-乘法运算
    三:排序-幸运数字
    二:排序-果园
  • 原文地址:https://www.cnblogs.com/shenben/p/6664497.html
Copyright © 2011-2022 走看看