匈牙利算法复杂度o(VE),HK复杂度(sqrt(v)E),这题建图就要3000*3000,用二分优化完再匈牙利爆栈了,只能用HK了,这个模板原来用过,发现ny就没有用,nx是x方的点数
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<ctime>
#include<algorithm>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define LINF 1e18
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=5000;
const int mod=1e4+7;
int m,n,rain;
int xx[maxn];
struct Guest
{
int x,y,v;
}gu[maxn],um[maxn];
int cmp(Guest a,Guest b)
{
return a.x<b.x;
}
int cx[maxn];
int cy[maxn];
int nx;
int dx[maxn];
int dy[maxn];
int dis;
int bmask[maxn];
int head[maxn],tot=0;
struct Edge
{
int v,nex;
Edge(){}
Edge(int v,int nex):v(v),nex(nex){}
}bmap[3001*3001];
void add_edge(int u,int v)
{
bmap[tot].nex=head[u];
bmap[tot].v=v;
head[u]=tot++;
}
bool searchpath()
{
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=1;i<=nx;i++)
{
if(cx[i]==-1)
{
Q.push(i);
dx[i]=0;
}
}
while(!Q.empty())
{
int u=Q.front();
Q.pop();
if(dx[u]>dis) break;
for(int i=head[u];i!=-1;i=bmap[i].nex)
{
int v=bmap[i].v;
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(cy[v]==-1)dis=dy[v];
else
{
dx[cy[v]]=dy[v]+1;
Q.push(cy[v]);
}
}
}
}
return dis!=INF;
}
int findpath(int u)
{
for(int i=head[u];i!=-1;i=bmap[i].nex)
{
int v=bmap[i].v;
if(bmask[v]==0 && dy[v]==dx[u]+1)
{
bmask[v]=1;
if(cy[v]!=-1 && dis==dy[v])continue;
if(cy[v]==-1 || findpath(cy[v]))
{
cx[u]=v;
cy[v]=u;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
int res=0;
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
while(searchpath())
{
memset(bmask,0,sizeof(bmask));
for(int i=1;i<=nx;i++)
{
if(cx[i]==-1)
{
res+=findpath(i);
}
}
}
return res;
}
int main()
{
int t,cas=1;
scanf("%d",&t);
while(t--){
memset(head,-1,sizeof head);
tot=0;
scanf("%d",&rain);
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d%d%d",&gu[i].x,&gu[i].y,&gu[i].v);
scanf("%d",&n);
nx=m;
for(int i=1;i<=n;i++)scanf("%d%d",&um[i].x,&um[i].y);
sort(um+1,um+1+n,cmp);
for(int i=1;i<=n;i++)xx[i]=um[i].x;
for(int i=1;i<=m;i++){
int l=lower_bound(xx+1,xx+1+n,gu[i].x-rain*gu[i].v)-xx;
int r=lower_bound(xx+1,xx+1+n,gu[i].x+rain*gu[i].v)-xx;
for(int j=l;j<=r && j<=n;j++){
int x=um[i].x,y=um[i].y;
if((gu[j].x-x)*(gu[j].x-x)+(gu[j].y-y)*(gu[j].y-y)
<=gu[j].v*gu[j].v*rain*rain)add_edge(i,j);
}
}
printf("Scenario #%d:\n%d\n\n",cas++,MaxMatch());
}
return 0;
}