- 题意: 给出m个点和n个人,每个人有一个速度,可以跑向一个点,但每个点只能被一个人占领
- 思路: 每个人和每个点都建一个点,如果人能跑到点则连一条边,求最大匹配即可.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 3050;
int uN,vN,t;
struct point{
int x,y;
point(){}
point(int x,int y):x(x),y(y){}
};
point a[N],b[N];
int vor[N];
int Mx[N],My[N];
// Mx 表示左集合顶点所匹配的右集合顶点序号, My 相反
int dx[N],dy[N];
// dx 表示左集合i顶点距离编号 dy 为右集合
int used[N];
int dis;
vector<int> g[N];
// 寻找增广路径集,每次只寻找当前最短的增广路
bool SearchP(){
queue<int> Q;
dis = INF;
memset(dy,-1,sizeof dy);
memset(dx,-1,sizeof dx);
for(int i=1;i<=uN;++i){
if(Mx[i] == -1){ //将未匹配的节点入队,并初始化其距离为0
Q.push(i);
dx[i] = 0;
}
}
while(!Q.empty()){
int u = Q.front();
Q.pop();
if(dx[u] > dis) break;
int sz = g[u].size();
for(int i=0;i<sz ;++i){
int v = g[u][i];
if(dy[v] == -1){
dy[v] = dx[u] +1;
if(My[v] == -1) dis = dy[v]; // 找到了一条增广路,dis为增广路终点的编号
else{
dx[My[v]] = dy[v]+1;
Q.push(My[v]);
}
}
}
}
return dis!=INF;
}
bool DFS(int u){
int sz = g[u].size();
for(int i=0;i<sz;++i){
int v = g[u][i];
if(!used[v] && dy[v] == dx[u]+1){ // 当前节点没有匹配,且距离上一节点+1
used[v] = true;
if(My[v] != -1 && dy[v]==dis) continue; // v已经被匹配且已到所有存在的增广路终点的编号,不可能存在增广路
if(My[v] == -1 || DFS(My[v])){
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
}
int MaxMatch(){
int res = 0;
memset(Mx,-1,sizeof Mx);
memset(My,-1,sizeof My);
while(SearchP()){
memset(used,0,sizeof used);
for(int i=1;i<=uN;++i){
if(Mx[i]==-1 && DFS(i)){
res++;
}
}
}
return res;
}
int check(int u,int v){
double dis = (a[u].x - b[v].x)*(a[u].x - b[v].x)*1.0 +1.0*(a[u].y-b[v].y)*(a[u].y-b[v].y);
double len = vor[u]*t*t*vor[u];
return len >= dis;
}
void solve(){
memset(g,0,sizeof g);
scanf("%d%d",&t,&uN);
for(int i=1;i<=uN;++i){
scanf("%d%d%d",&a[i].x,&a[i].y,&vor[i]);
}
scanf("%d",&vN);
for(int i=1;i<=vN;++i){
scanf("%d%d",&b[i].x,&b[i].y);
}
for(int i=1;i<=uN;++i){
for(int j=1;j<=vN;++j){
if(check(i,j)){
g[i].push_back(j);
}
}
}
printf("%d\n",MaxMatch());
}
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
printf("Scenario #%d:\n",i);
solve();
puts("");
}
return 0;
}