Way Selection【二分图最大匹配】

导航

    • 题意
    • 分析
    • 参考代码

题意

小杉家族r个人正在一片空地上散步,突然,外星人来了……
留给小杉家族脱逃的时间只有t秒,每个小杉都有一个跑的速度v
总共有a个传送点,小杉们必须在t秒内到达传送点才能脱逃
当一个小杉进入一个传送点以后,该传送点就会消失
现在请你安排一种方案,使脱逃的小杉尽可能的多

分析

r个人是X集合,a个传送点是Y集合。如果第i个人能在t时间内到达第j个传送点,则ri向aj连边。最后求最大匹配

参考代码

#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define in rad()
inline int rad(){
	int x=0,f=1;char c=getchar();while(c>'9'||c<'0')c=getchar();
	if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
	return x*f;
}
const int maxn=1e3+10;
const int maxm=4e5+100;
const int inf=1e9;
int r,a,t;
int mp[maxn][maxn],vis[maxn],match[maxn];
double x[maxn],y[maxn];
int ok(double xx,double yy,double v,int k){
	double len=v*t;
	double dis=sqrt((xx-x[k])*(xx-x[k]) + (yy-y[k])*(yy-y[k]));
	return len>=dis;
}
int find(int x){
	for(int i=1;i<=r;i++)
		if(mp[x][i] && !vis[i]){
			vis[i]=1;
			if(match[i]==-1 || find(match[i])){
				match[i]=x;return 1;
			}
		}
	return 0;
}
int km(){
	int ans=0;
	memset(match,-1,sizeof(match));
	for(int i=1;i<=a;i++){
		memset(vis,0,sizeof(vis));
		ans+=find(i);
	}
	return ans;
}
int main(){
	r=in;a=in;t=in;
	for(int i=1;i<=a;i++)
		scanf("%lf%lf",x+i,y+i);
	for(int i=1;i<=r;i++){
		double tx,ty,v;
		scanf("%lf%lf%lf",&tx,&ty,&v);
		for(int j=1;j<=a;j++)
			if(ok(tx,ty,v,j))mp[j][i]=1;
	}	
	cout<<km();
	return 0;
}	

你可能感兴趣的:(二分图)