看到了M,N<=100于是才10000个点,直接建图吧,然后想想想=>看师兄题解。。。。。
将行和列作为节点,行和S相连,列和T相连,然后不是障碍的ij相连,c=1;
关键是能想到反过来求最多可以拿走多少个士兵,就能够转换为maxflow了。
--------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int inf=0x3f3f3f;
int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){
if(c==‘-‘) f=-1;
c=getchar();
}
while(isdigit(c)){
x=x*10+c-‘0‘;
c=getchar();
}
return x*f;
}
struct edge{
int to,cap;
edge *next,*rev;
};
edge e[400000],*pt=e,*cur[205],*head[205],*p[205];
int d[205],cnt[205],vis[105][105],a[105],b[105],l[105],c[105];
void add(int u,int v,int d){
pt->to=v;
pt->cap=d;
pt->next=head[u];
head[u]=pt++;
}
void adde(int u,int v,int d){
add(u,v,d);
add(v,u,0);
head[u]->rev=head[v];
head[v]->rev=head[u];
}
int maxflow(int s,int t,int n){
int flow=0,a=inf,x=s;
clr(d,0);
clr(cnt,0);
cnt[0]=n;
while(d[s]<n){
edge *ee;
for(ee=cur[x];ee;ee=ee->next)
if(ee->cap>0&&d[ee->to]+1==d[x])
break;
if(ee){
p[ee->to]=cur[x]=ee;
a=min(a,ee->cap);
x=ee->to;
if(x==t){
while(x!=s){
p[x]->cap-=a;
p[x]->rev->cap+=a;
x=p[x]->rev->to;
}
flow+=a;
a=inf;
}
}
else{
if(!--cnt[d[x]]) break;
d[x]=n;
for(ee=head[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]+1<d[x]){
d[x]=d[ee->to]+1;
cur[x]=ee;
}
}
cnt[d[x]]++;
if(x!=s) x=p[x]->rev->to;
}
}
return flow;
}
int main(){
int L=read(),C=read(),k=read(),s=0,t=L+C+1,n=t+1;
rep(i,L) l[i]=read();
rep(i,C) c[i]=read();
clr(vis,1);clr(a,0);clr(b,0);
rep(i,k){
int u=read(),v=read();
vis[u][v]=0;a[u]++;b[v]++;
}
rep(i,L) if(C-a[i]<l[i]) {
puts("JIONG!");
return 0;
}
rep(i,C) if(L-b[i]<c[i]){
puts("JIONG!");
return 0;
}
rep(i,L) adde(s,i,C-a[i]-l[i]);
rep(i,C) adde(L+i,t,L-b[i]-c[i]);
rep(i,L)
rep(j,C){
if(vis[i][j])
adde(i,L+j,1);
}
printf("%d\n",L*C-k-maxflow(s,t,n));
return 0;
}
--------------------------------------------------------------------------------------
1458: 士兵占领
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 705 Solved: 408
[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