1458: 士兵占领
Time Limit: 10 Sec Memory Limit: 64 MBDescription
有一个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
SOLUTION
这题就是如果一个士兵所在的行和列都需要士兵,那么这个士兵就可以做出两个贡献,在刚开始的时候统计最差的士兵数量之和,也就是需要就加上,然后行和列建边,跑一边最大流,找出最多的可以做出两个贡献的士兵,然后用sum减去即可
找最小的值可以考虑最大流再相减
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 # define INF 100000 9 using namespace std; 10 int n,m,lim; 11 int hang[110],lie[110]; 12 bool pan[110][110]; 13 int S,T,SUM; 14 struct node{ 15 int u,v,w,nxt; 16 }g[20010]; 17 int adj[20010],e; 18 void add(int u,int v,int w){ 19 g[e].v=v; g[e].u=u; g[e].w=w; 20 g[e].nxt=adj[u]; adj[u]=e++; 21 } 22 bool Jud(){ 23 bool ok=1; 24 for(int i=1;i<=n;i++){ 25 int he=0; 26 for(int j=1;j<=m;j++){ 27 if(!pan[i][j]) he++; 28 } 29 if(he<hang[i]){ok=0;break;} 30 } 31 if(ok){ 32 for(int j=1;j<=m;j++){ 33 int he=0; 34 for(int i=1;i<=n;i++){ 35 if(!pan[i][j]) he++; 36 } 37 if(he<lie[j]){ok=0;break;} 38 } 39 } 40 return ok; 41 } 42 int dep[310]; 43 bool BFS(){ 44 memset(dep,0,sizeof(dep)); 45 queue<int> q; 46 dep[S]=1; q.push(S); 47 int k; 48 while(!q.empty()){ 49 k=q.front(); q.pop(); 50 for(int i=adj[k];i!=-1;i=g[i].nxt){ 51 int v=g[i].v; 52 if(g[i].w && !dep[v]){ 53 dep[v]=dep[k]+1; 54 if(v==T) return 1; 55 q.push(v); 56 } 57 } 58 } 59 return 0; 60 } 61 int dfs(int x,int fw){ 62 if(x==T) return fw; 63 int tmp=fw,k; 64 for(int i=adj[x];i!=-1;i=g[i].nxt){ 65 int v=g[i].v; 66 if(g[i].w && tmp && dep[v]==dep[x]+1){ 67 k = dfs(v,min(g[i].w,tmp)); 68 if(!k){ 69 dep[v]=0; 70 continue; 71 } 72 g[i].w-=k; g[i^1].w+=k; tmp-=k; 73 } 74 } 75 return fw-tmp; 76 } 77 void work(){ 78 memset(adj,-1,sizeof(adj)); 79 S=0; T=110; 80 for(int i=1;i<=n;i++) add(S,i,hang[i]), add(i,S,0); 81 int jia=101; 82 for(int j=1;j<=m;j++) add(j+jia,T,lie[j]), add(T,j+jia,0); 83 for(int i=1;i<=n;i++){ 84 for(int j=1;j<=m;j++){ 85 if(pan[i][j]) continue; 86 add(i,j+jia,1); add(j+jia,i,0); 87 } 88 } 89 int he=0,tan; 90 while(BFS()){ 91 while(tan=dfs(S,INF)) he+=tan; 92 } 93 printf("%d",SUM-he); 94 } 95 int main(){ 96 //freopen("a.in","r",stdin); 97 //freopen("a.out","w",stdout); 98 scanf("%d%d%d",&n,&m,&lim); 99 for(int i=1;i<=n;i++) scanf("%d",&hang[i]), SUM+=hang[i]; 100 for(int i=1;i<=m;i++) scanf("%d",&lie[i]), SUM+=lie[i]; 101 int x,y; 102 for(int i=1;i<=lim;i++){ 103 scanf("%d%d",&x,&y); 104 pan[x][y]=1; 105 } 106 S=0; T=110; 107 bool ok=Jud(); 108 if(!ok){ 109 printf("JIONG "); 110 return 0; 111 } 112 work(); 113 return 0; 114 }