1458: 士兵占领
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1099 Solved: 618
[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
邻接表开小 怒RE n 发
本来想写上下界 然而。。。不会写。。。
看看以后能不能填上坑
所以
贴上hzwer的题解:
此题的思路是先放满棋盘,然后考虑最多可以删多少个。。。
某一行和某一列的可以放的格子数小于需求就直接jiong掉
然后从源向每一行连边,流量为可以放的格子数 - 需求的格子数(也就是可以删多少格子)
从每一列向汇,同上.
从每一个非障碍的格子的行向列连边流量为1
跑一遍最大流即可ans=可放格子数-maxflow
咦怎么感觉他的更科学。。。
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f*x;
}
const int N=110;const int inf=0X7f7f7f7f;
int n,m,k,ecnt=1,last[N<<1],L[N],C[N],antiL[N],antiC[N],d[N<<1],q[N<<1],a[N][N],S,T=(N<<1)-2,ans;
struct EDGE{int to,nt,val;}e[N<<7];
inline void readd(int u,int v,int val)
{e[++ecnt]=(EDGE){v,last[u],val};last[u]=ecnt;}
inline void add(int u,int v,int val)
{readd(u,v,val);readd(v,u,0);}
bool bfs()
{
memset(d,0,sizeof(d));
int t=0,w=1;q[t]=S;d[S]=1;
while(t<w)
{
int temp=q[t++];
for(int i=last[temp];i;i=e[i].nt)
if(e[i].val&&!d[e[i].to])
{d[e[i].to]=d[temp]+1;q[w++]=e[i].to;}
}
if(d[T])return true;else return false;
}
inline int dfs(int u,int lim)
{
if(u==T||lim==0)return lim;
int ret=0;
for(int i=last[u];i;i=e[i].nt)if(d[e[i].to]==d[u]+1)
{
int temp=dfs(e[i].to,min(e[i].val,lim));
e[i].val-=temp;e[i^1].val+=temp;
lim-=temp;ret+=temp;
if(lim==0)break;
}
if(!ret)d[u]=-1;
return ret;
}
void dinic()
{while(bfs()){ans+=dfs(S,inf);}}
int main()
{
n=read();m=read();k=read();int sum=n*m-k;
for(int i=1;i<=n;i++)L[i]=read();
for(int i=1;i<=m;i++)C[i]=read();
for(int i=1;i<=k;i++)a[read()][read()]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{if(a[i][j])antiL[i]++,antiC[j]++;else add(i,n+j,1);}
for(int i=1;i<=n;i++)
if(antiL[i]+L[i]>m){puts("JIONG!");return 0;}
else add(S,i,m-antiL[i]-L[i]);
for(int i=1;i<=m;i++)
if(antiC[i]+C[i]>n){puts("JIONG!");return 0;}
else add(i+n,T,n-antiC[i]-C[i]);
// for(int i=1;i<=ecnt;i++)cout<<e[i].to<<endl;
dinic();
printf("%d\n",sum-ans);
return 0;
}
/*
4 4 4
1 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
Sample Output
4
*/