原图地址:点击打开链接
该题即使简单的二分图最大匹配问题,用匈牙利算法O(n*m)会超时,所以这里我们用Hopcroft-Karp算法,这个算法的时间复杂度为O(sqrt(n)*m).如果不了解这个算法可以看另一篇博客点击打开链接
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
#include<math.h>
#define INF 1<<31-1
using namespace std;
struct Position
{
int x;
int y;
double speed;
}peo[3010],umb[3010];
vector<int>edge[3010];
bool used[3010];
int fx[3010];
int fy[3010];
int dx[3010];
int dy[3010];
int len;
int m,n,k=0;
bool judge(Position p1,Position p2,int time)
{
double d=sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
if(p1.speed*time>=d)
return true;
return false;
}
bool searchPath() //找寻最短的增广路径
{
int i;
queue<int>Q;
len=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(i=1;i<=m;i++)
{
if(fx[i]==-1)
{
Q.push(i);
dx[i]=0;
}
}
while(!Q.empty())
{
int u=Q.front();
Q.pop();
if(dx[u]>len)
break;
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(fy[v]==-1)
len=dy[v];
else
{
dx[fy[v]]=dy[v]+1;
Q.push(fy[v]);
}
}
}
}
if(len!=INF)
return true;
return false;
}
bool find(int u)
{
int i;
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(!used[v]&&dy[v]==dx[u]+1)
{
used[v]=true;
if(fy[v]!=-1&&dy[v]==len)
continue;
if(fy[v]==-1||find(fy[v]))
{
fy[v]=u;
fx[u]=v;
return true;
}
}
}
return false;
}
int solve()
{
int i,res=0;
memset(fy,-1,sizeof(fy));
memset(fx,-1,sizeof(fx));
while(searchPath())
{
memset(used,0,sizeof(used));
for(i=1;i<=m;i++)
{
if(fx[i]==-1&&find(i))
res++;
}
}
return res;
}
int main()
{
int i,j,t,time;
scanf("%d",&t);
while(t--)
{
scanf("%d",&time);
scanf("%d",&m);
for(i=1;i<=m;i++)
scanf("%d%d%lf",&peo[i].x,&peo[i].y,&peo[i].speed);
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d%d",&umb[i].x,&umb[i].y);
for(i=1;i<=m;i++)
{
edge[i].clear();
for(j=1;j<=n;j++)
{
if(judge(peo[i],umb[j],time))
{
edge[i].push_back(j);
}
}
}
int res=solve();
printf("Scenario #%d:\n%d\n\n",++k,res);
}
}