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; }
时间: 2024-10-21 15:08:17