bzoj1458: 士兵占领

1458: 士兵占领

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

Sample Output

4
数据范围
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
",ans);
52 }
View Code
原文地址:https://www.cnblogs.com/Bloodline/p/5886471.html