bzoj1458: 士兵占领
1458: 士兵占领
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 920 Solved: 518
[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
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
数据范围
M, N <= 100, 0 <= K <= M * N
题解by黄学长:
此题的思路是先放满棋盘,然后考虑最多可以删多少个。。。
某一行和某一列的可以放的格子数小于需求就直接jiong掉
然后从源向每一行连边,流量为可以放的格子数 - 需求的格子数(也就是可以删多少格子)
从每一列向汇,同上.
从每一个非障碍的格子的行向列连边流量为1
跑一遍最大流即可ans=可放格子数-maxflow
1 #include<bits/stdc++.h> 2 #define rep(i,l,r) for(int i=l;i<=r;++i) 3 const int N=102333,inf=2147483647; 4 using namespace std; 5 int head[N],dis[N],tot=1,n,m,K,ans,x,y,l[N],l1[N],p[N],p1[N],T; 6 bool mp[123][123]; 7 struct zs{ 8 int to,next,w; 9 }e[N]; 10 inline bool bfs(){ 11 for(int i=0;i<=T;i++) dis[i]=-1; queue<int>q; q.push(0); dis[0]=0; 12 while(!q.empty()) { 13 int x=q.front(); q.pop(); 14 for(int k=head[x];k;k=e[k].next) 15 if(dis[e[k].to]<0 && e[k].w>0) { 16 dis[e[k].to]=dis[x]+1; q.push(e[k].to); 17 } 18 } 19 if(dis[T]>0) return 1;else return 0; 20 } 21 int find(int x,int low){ 22 if(x==T) return low; 23 int delta=low,now; 24 for(int k=head[x];k;k=e[k].next) 25 if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 26 now=find(e[k].to,min(e[k].w,delta)); 27 e[k].w-=now; e[k^1].w+=now; delta-=now; 28 if(!delta) return low; 29 } 30 dis[x]=-1; 31 return low-delta; 32 } 33 inline void ins(int u,int v,int w){ 34 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w; 35 } 36 inline void insert(int u,int v,int w){ 37 ins(u,v,w); ins(v,u,0); 38 } 39 int main(){ 40 scanf("%d%d%d",&n,&m,&K); 41 ans=m*n; 42 T=1+n+m; 43 rep(i,1,n) scanf("%d",&l[i]); 44 rep(i,1,m) scanf("%d",&l1[i]); 45 rep(i,1,K) scanf("%d%d",&x,&y),mp[x][y]=1,p[x]++,p1[y]++,--ans; 46 rep(i,1,n) rep(j,1,m) if(!mp[i][j]) insert(i,j+n,1); 47 rep(i,1,n) insert(0,i,m-p[i]-l[i]); 48 rep(i,1,m) insert(i+n,T,n-p1[i]-l1[i]); 49 while(bfs()) ans-=find(0,inf); 50 for(int k=head[0];k;k=e[k].next) if(e[k].w){puts("JIONG!"); return 0;} 51 printf("%d\n",ans); 52 }