题意:给出t组数据,每组数据有一个时间T,n个人的坐标(x,y)即速度s,又给出m把雨伞的坐标(x,y),求在T秒时最多有多少人拿到雨伞(不淋雨).
题解:由于数据很大,故不能用匈牙利,套Hopcroft-Carp模板即可,时间复杂度为O(sqrt(V)*E).
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 3300;
struct Hopcroft_Karp {
int n1, n2, ans; //n1为左边的点数,n2为右边的点数,ans为最大匹配数
vector<int>g[maxn]; //g[i]表示与左边i点相匹配的点
int mx[maxn], my[maxn];
//mx[i]表示最大匹配中与左边的i相连的点,my[i]表示最大匹配中与右边的点相连的点
int dx[maxn], dy[maxn];
bool vis[maxn];
queue<int>q;
bool find(int u) {
for (int i = 0; i < g[u].size(); i++) {
if (!vis[g[u][i]] && dy[g[u][i]] == dx[u] + 1) {
vis[g[u][i]] = true;
if (!my[g[u][i]] || find(my[g[u][i]])) {
mx[u] = g[u][i];
my[g[u][i]] = u;
return true;
}
}
}
return false;
}
void matching() {//跑一遍即可得到答案ans的结果
memset(mx, 0, sizeof(mx));
memset(my, 0, sizeof(my));
ans = 0;
while (1) {
bool flag = false;
while (!q.empty())q.pop();
memset(dx, 0, sizeof(dx));
memset(dy, 0, sizeof(dy));
for (int i = 1; i <= n1; i++)
if (!mx[i])q.push(i);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = 0; i < g[u].size(); i++) {
if (!dy[g[u][i]]) {
dy[g[u][i]] = dx[u] + 1;
if (my[g[u][i]]) {
dx[my[g[u][i]]] = dy[g[u][i]] + 1;
q.push(my[g[u][i]]);
}
else
flag = true;
}
}
}
if (!flag)break;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n1; i++)
if (!mx[i] && find(i))ans++;
}
}
void init(int nn1, int nn2) {
n1 = nn1; n2 = nn2;
for (int i = 1; i <= n1; i++)
g[i].clear();
}
}h;
struct node {
double x, y, s;
}a[maxn], b[maxn];
int main() {
int t;
double T;
scanf("%d", &t);
for (int cas = 1; cas <= t; cas++) {
scanf("%lf", &T);
scanf("%d", &h.n1);
for (int i = 1; i <= h.n1; i++)
scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].s);
scanf("%d", &h.n2);
for (int i = 1; i <= h.n2; i++)
scanf("%lf%lf", &b[i].x, &b[i].y);
h.init(h.n1, h.n2);
for (int i = 1; i <= h.n1; i++)
for (int j = 1; j <= h.n2; j++) {
if (a[i].s*T >= sqrt((a[i].x - b[j].x)*(a[i].x - b[j].x) + (a[i].y - b[j].y)*(a[i].y - b[j].y)))
h.g[i].push_back(j);
}
h.matching();
printf("Scenario #%d:\n%d\n\n", cas, h.ans);
} return 0;
}