bzoj1458士兵占领
Posted Troy Ricardo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1458士兵占领相关的知识,希望对你有一定的参考价值。
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
题解:
最大流第一题。orz黄学长。
问最小需要点数转化一下,就是最大能不放的位置。以S为原点,向每行连一条容量为n-l[i]-在该行上不能放置点数,以T为汇点,每列向T连一条m-c[i]-在该列上不能放置数的边。再把每行对应的点与可以连接的列对应点连一条容量为1的边,最大流显然就是要求的最大数。
然后用总点数减去这些就行。
1 #include<cstdio> 2 #include<cstring> 3 const int T=201; 4 const int S=0; 5 inline int min(int a,int b){return a<b?a:b;} 6 inline int read(){ 7 char ch=getchar(); 8 int f=1,x=0; 9 while(!(ch>=‘0‘&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();} 10 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+(ch-‘0‘);ch=getchar();} 11 return x*f; 12 } 13 int m,n,k; 14 const int N=110; 15 int l[N],c[N]; 16 bool vis[N][N],used[N]; 17 int rel[N],rec[N]; 18 int tot,ans; 19 struct edges { 20 int v,cap;edges *last; 21 }edge[N<<8],*head[N<<8],*cur[N<<8];int cnt; 22 inline void insert(int u,int v,int w){ 23 edge[cnt].v=v;edge[cnt].last=head[u];edge[cnt].cap=w;head[u]=edge+cnt;cnt++; 24 edge[cnt].v=u;edge[cnt].last=head[v];edge[cnt].cap=0;head[v]=edge+cnt;cnt++; 25 } 26 int q[N<<5]; 27 int dis[N<<5]; 28 int h,t; 29 bool bfs(){ 30 memset(dis,0,sizeof(dis)); 31 dis[S]=1,q[1]=S;h=t=1; 32 int u,v; 33 while(h<=t){ 34 u=q[h++]; 35 for(edges *i=head[u];i;i=i->last) 36 if(i->cap&&!dis[i->v]) 37 dis[i->v]=dis[u]+1,q[++t]=i->v; 38 } 39 if(dis[T]) return 1; 40 else return 0; 41 } 42 43 int dfs(int u,int w){ 44 if(u==T||w==0) return w; 45 int ret=0; 46 for(edges *i=head[u];i;i=i->last)if(i->cap&&(dis[i->v]==dis[u]+1)){ 47 int f=dfs(i->v,min(i->cap,w)); 48 i->cap-=f,edge[(i-edge)^1].cap+=f; 49 w-=f,ret+=f; 50 if(!w) break; 51 } 52 if(!ret) dis[u]=-1; 53 return ret; 54 } 55 56 inline int dinic(){ 57 int ret=0; 58 while(bfs()) ret+=dfs(S,0x7fffffff); 59 return ret; 60 } 61 int main() 62 { 63 m=read(),n=read(),k=read(); 64 for(int i=1;i<=m;i++) 65 l[i]=n-read(); 66 for(int i=1;i<=n;i++) 67 c[i]=m-read(); 68 for(int i=1,x,y;i<=k;i++) 69 { 70 x=read(),y=read(); 71 vis[x][y]=1; 72 rel[x]++,rec[y]++; 73 if(rel[x]>l[x]){puts("JIONG!");return 0;} 74 if(rel[y]>l[y]){puts("JIONG!");return 0;} 75 } 76 tot=n*m-k; 77 for(int i=1;i<=m;i++) 78 insert(0,i,l[i]-rel[i]); 79 for(int i=1;i<=n;i++) 80 insert(m+i,T,c[i]-rec[i]); 81 for(int i=1;i<=m;i++) 82 for(int j=1;j<=n;j++) 83 if(!vis[i][j])insert(i,j+m,1); 84 ans=dinic(); 85 printf("%d\n",tot-ans); 86 }
以上是关于bzoj1458士兵占领的主要内容,如果未能解决你的问题,请参考以下文章