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

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士兵占领的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1458: 士兵占领 -- 最大流

BZOJ-1458士兵占领 最大流

bzoj1458: 士兵占领 网络流

bzoj1458士兵占领

bzoj 1458: 士兵占领

BZOJ1458: 士兵占领