在一个露天party里,宾客们在狂欢,还有ts时间将要下雨,现场有m个人,地上有n个雨伞,各自有着不同的坐标,人有着各自的奔跑速度,一个伞只能够容纳一个人,问, 有多少个人可以不被雨淋湿。
m个人,n把伞,典型的匹配问题,只要能跑到的就说明人和该伞有关系,然后就是二分匹配,但是普通的二分匹配会超时(时间复杂度是O(VE)),所以要用到二分匹配的HK算法(同时找到多条增广轨,时间复杂度O(V^0.5*E)),来优化整个匹配过程。
比较好的博客(HK算法):
http://files.cnblogs.com/files/liuxin1.pdf
#include
#include
#include
#include
#include
using namespace std;
const int INF=0x3f3f3f3f;
const double eps=1e-6;
int m,n,limit;
bool mp[3000+10][3000+10];
bool vis[3000+10];
int linkX[3000+10],linkY[3000+10];//记录该点已经被谁连接了
int depthX[3000+10],depthY[3000+10];//记录下每一个点的深度
struct people
{
double x,y,v;
} p[3000+10];
struct un
{
double x,y;
} s[3000+10];
double dis(double x,double y,double x2,double y2)
{
return sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
}
bool seachAP()
{
limit=INF;
queue<int> q;
memset(depthX,-1,sizeof(depthX));
memset(depthY,-1,sizeof(depthY));
for(int i=1; i<=m; i++)
{
if(linkX[i]==-1)//把尚未匹配的假如队列,一个一个用深度标记之后,y利用dfs一起匹配,这是优化的地方
{
q.push(i);
depthX[i]=0;
}
}
while(!q.empty())
{
int w=q.front();
q.pop();
if(depthX[w]>limit) break;//如果找到了能够匹配的,就退出,但是有人会说为啥不在找到的时候直接退出,因为要标记所有长度深度不大于limit的组合
for(int i=1; i<=n; i++)
{
if(mp[w][i]&&depthY[i]==-1)
{
depthY[i]=depthX[w]+1;
if(linkY[i]==-1)
{
limit=depthY[i];//limit赋值
}
else
{
depthX[linkY[i]]=depthY[i]+1;
q.push(linkY[i]);//增广路
}
}
}
}
return limit!=INF;
}
bool dfs(int x)
{
for(int i=1; i<=n; i++)
{
if(!vis[i]&&mp[x][i]&&depthY[i]==depthX[x]+1)
{
vis[i]=1;
if(linkY[i]!=-1&&depthY[i]==limit) continue;
if(linkY[i]==-1||dfs(linkY[i]))
{
linkX[x]=i;
linkY[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int T,cases=1;
scanf("%d",&T);
while(T--)
{
double t;
scanf("%lf",&t);
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].v);
}
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%lf%lf",&s[i].x,&s[i].y);
}
memset(mp,0,sizeof(mp));
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
double d=dis(p[i].x,p[i].y,s[j].x,s[j].y);
if(d/p[i].v-t1;
}
}
}
int res=0;
memset(linkX,-1,sizeof(linkX));
memset(linkY,-1,sizeof(linkY));
while(seachAP())
{
memset(vis,0,sizeof(vis));
for(int i=1; i<=m; i++)
{
if(linkX[i]==-1&&dfs(i))
{
res++;
}
}
}
printf("Scenario #%d:\n",cases++);
printf("%d\n\n",res);
}
}