题目描述
战犯们企图逃离监狱,他们详细地计划了如何逃出监狱本身,逃出监狱之后他们希望在附近的一个村子里找到掩护。村子(下图中的B)和监狱(图中的A)中间有一个峡谷,这个峡谷也是有士兵守卫的。守卫峡谷的士兵们坐在岗哨上很少走动,每个士兵的观察范围是100米。士兵所处位置决定了战犯们能否安全通过峡谷,安全通过的条件就是在任何时刻战犯们距离最近的士兵大于100米。
给定峡谷的长、宽和每个士兵在峡谷中的坐标,假定士兵的位置一直保持不变,请你写一个程序计算战犯们能否不被士兵发现,顺利通过峡谷。如果不能,那么战犯们最少需要消灭几个士兵才能安全通过峡谷(无论士兵是否被另一个士兵看到,他都可以被消灭)。
题目大意
求最小割
数据范围
1≤W≤50000
1≤L≤50000
1≤N≤250
样例输入
130 340 5
10 50
130 130
70 170
0 180
60 260
样例输出
1
解题思路
最小割,如果两个士兵能互相看见,则前一个向后一个连边。如果一个士兵能看到左边界,则原点向这个士兵连边,如果一个士兵能看见右边界,则这个士兵向汇点连边。然后求最小割。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
struct pos{long long x,y;}w[1000005];
int S,T,N,cnt=0,h[1000005],dis[1000005],GAP[1000005];
struct node{int to,next,v,pair;}e[1000005];
int SAP(int x,int Maxflow){
if(x==T)return Maxflow;
int tmp=Maxflow;
for(int p=h[x];p;p=e[p].next){
int y=e[p].to;
int flow=min(tmp,e[p].v);
if(flow&&dis[x]==dis[y]+1){
int ret=SAP(y,flow);
tmp-=ret;
e[p].v-=ret;
e[e[p].pair].v+=ret;
if(!tmp||dis[S]==N)return Maxflow-tmp;
}
}
if(--GAP[dis[x]]==0)dis[S]=N;
else GAP[++dis[x]]++;
return Maxflow-tmp;
}
void AddEdge(int x,int y,int v,int pair){e[cnt]=(node){y,h[x],v,pair};h[x]=cnt;}
void AddEdge(int x,int y,int v){AddEdge(x,y,v,++cnt+1);AddEdge(y,x,0,++cnt-1);}
long long Getdis(int a,int b){return (w[a].x-w[b].x)*(w[a].x-w[b].x)+(w[a].y-w[b].y)*(w[a].y-w[b].y);}
int main(){
int L=Getint(),W=Getint(),n=Getint();
for(int i=1;i<=n;i++)w[i]=(pos){Getint(),Getint()};
memset(h,0,sizeof(h));
memset(e,0,sizeof(e));
memset(dis,0,sizeof(dis));
memset(GAP,0,sizeof(GAP));
N=n*2+2;
GAP[0]=N;
cnt=0;
S=0,T=n*2+1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(Getdis(i,j)<=40000LL)
AddEdge(i+n,j,1<<30),AddEdge(j+n,i,1<<30);
for(int i=1;i<=n;i++){
if(w[i].y<=100)AddEdge(S,i,1<<30);
if(W-w[i].y<=100)AddEdge(i+n,T,1<<30);
}
for(int i=1;i<=n;i++)
AddEdge(i,i+n,1);
int Ans=0;
while(dis[S]<N)Ans+=SAP(S,1<<30);
cout<<Ans;
return 0;
}