首页 > 代码库 > 1458: 士兵占领

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

 

1458: 士兵占领