题目地址:点击打开链接
题意:有n个人m把伞,在t秒后要下雨,给出每个人和伞的坐标和每个人走路的速度,问你在t秒内最多能有几个人能拿
到伞(每把伞只能一个人用)。n,m<=3000。
匈牙利算法的时间复杂度是O(n*E),这题的边的数量达到了3000*3000,所以用匈牙利肯定会T,Hopcroft-Carp的时间
复杂度是O(sqrt(n)*E).
还没能理解Hopcroft-Carpz的原理,先用着模板吧。
代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
/* *******************************
* 二分图匹配(Hopcroft-Carp算法)
* 复杂度O(sqrt(n)*E)
* 邻接表存图,vector实现
* vector先初始化,然后假如边
* uN 为左端的顶点数,使用前赋值(点编号1开始)
*/
const int maxn = 3e3+5;
const int INF = 0x3f3f3f3f;
vector<int> g[maxn];
int uN;
int Mx[maxn], My[maxn];
int dx[maxn], dy[maxn];
int dis;
bool vis[maxn];
bool searchP()
{
queue<int> q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i = 1; i <= uN; i++)
{
if(Mx[i] == -1)
{
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];
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(!vis[v] && dy[v] == dx[u]+1)
{
vis[v] = 1;
if(My[v] != -1 && dy[v] == dis) continue;
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(vis, 0, sizeof(vis));
for(int i = 1; i <= uN; i++)
if(Mx[i] == -1 && dfs(i))
res++;
}
return res;
}
/******************************************************/
struct Point
{
int x, y, s;
void input1()
{
scanf("%d%d%d", &x, &y, &s);
}
void input2()
{
scanf("%d%d", &x, &y);
}
};
Point p1[maxn], p2[maxn];
int dis2(Point a, Point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main(void)
{
int T, t, ca = 1, n, m;
cin >> T;
while(T--)
{
for(int i = 0; i < maxn; i++)
g[i].clear();
scanf("%d%d", &t, &n);
for(int i = 1; i <= n; i++)
p1[i].input1();
scanf("%d", &m);
for(int i = 1; i <= m; i++)
p2[i].input2();
uN = n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(dis2(p1[i], p2[j]) <= p1[i].s*p1[i].s*t*t)
g[i].push_back(j);
printf("Scenario #%d:\n%d\n\n", ca++, MaxMatch());
}
return 0;
}