题意:
有n个雨伞,有m个人。
t min 后下雨。
问最多有多少个人可以拿到雨伞(一把伞,只能有一个人)
思路:
- 裸的二分图最大匹配。
- 把距离关系,转换一下,建图即可。
AC
#include<iostream>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#define fzhead EDGE(int _to,int _next)
#define fzbody to(_to), next(_next)
#define ll long long
using namespace std;
typedef pair<int,int> P;
const int maxn = 6050;//存的点最多是n+m
int vis[maxn];
struct EDGE{
int to,next;
EDGE(){}
fzhead:fzbody{}
}e[maxn*1500];
int cnt,n,m,p,ca = 0,T,t;
int head[maxn],con[maxn],dep[maxn];
int x[maxn],y[maxn],s[maxn];
void add(int bg,int to){e[++cnt]=EDGE(to,head[bg]);head[bg]=cnt;}
void init()
{
cnt = 0;
memset(head,-1,sizeof head);memset(vis,0,sizeof vis);memset(con,-1,sizeof con);
///init con to -1;
cin >> t >> n;
for(int i = 1;i <= n;++i) scanf("%d%d%d",&x[i],&y[i],&s[i]);
cin >> m;
for(int i = 1;i <= m;++i) scanf("%d%d",&x[i + n],&y[i + n]);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
{
int w = (x[i] - x[j + n]) * (x[i] - x[j + n]) + (y[i] - y[j + n])*(y[i] - y[j + n]);
int temp = t * s[i] * t * s[i];
if(temp >= w) add(i,j + n);
}
}
bool bfs()
{
memset(dep,0,sizeof dep);
queue<int> q;
while(q.size()) q.pop();
for(int i = 1;i <= n;++i)
if(con[i] == -1) q.push(i);
bool flag = 0;
while(q.size())
{
int u = q.front();q.pop();
for(int i = head[u];i != -1; i = e[i].next)
{
if(!dep[e[i].to])
{
dep[e[i].to] = dep[u] + 1;
if(con[e[i].to] == -1) flag = 1;
else dep[con[e[i].to]] = dep[e[i].to] + 1,q.push(con[e[i].to]);
}
}
}
return flag;
}
bool dfs(int u)
{
for(int i = head[u];i != -1; i = e[i].next)
{
int v = e[i].to;
if(dep[v] != dep[u] + 1) continue;
dep[v] = 0;
if(con[v] == -1 || dfs(con[v]))
{
con[u] = v;
con[v] = u;
return 1;
}
}
return 0;
}
void sol(){
int ans = 0;
while(bfs())
for(int i = 1;i <= n;++i) if(con[i] == -1 && dfs(i)) ans++;
printf("Scenario #%d:\n%d\n\n",++ca,ans);
}
int main()
{
cin>>T;
while(T--)
{
init();
sol();
}
}