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;
}

 

posted @ 2017-04-04 11:05  神犇(shenben)  阅读(304)  评论(0编辑  收藏  举报