这道题其实就是一个Hopcroft-Carp模板题
在匈牙利算法中,我们每次寻找一条增广路来增加匹配集合M.可以证明,每次找增广路的复杂度是O(E),一共需要增广O(V)次,因此总时间复杂度为O(VE).为了降低时间复杂度,在Hopcroft Karp算法中,我们在增加匹配集合M时,每次寻找多条增广路.可以证明,这样迭代次数最多为2*V^0.5,所以,时间复杂度就降到了O(V^0.5*E).
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
#define MAXN 3333
const int INF=1<<28;
int mx[MAXN], my[MAXN];
int dx[MAXN], dy[MAXN];
bool vis[MAXN];
vector<int> g[MAXN];
int nx, ny, t, dis;
struct point
{
int x, y, v;
}umb[MAXN], peo[MAXN];
bool dfs( int u )
{
for( int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if( !vis[v] && dy[v] == dx[u] + 1)
{
vis[v] = 1;
if( my[v] == -1 || dfs(my[v]))
{
my[v] = u;
mx[u] = v;
return true;
}
}
}
return false;
}
int solve()
{
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
int ans = 0;
while(1)
{
queue<int > que;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i = 1; i <= nx; i++)
if(mx[i] == -1) que.push(i), dx[i] = 0;
bool flag = false;
while(!que.empty())
{
int u = que.front();
que.pop();
for( int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(dy[v] == -1)
{
dy[v] = dx[u] + 1;
if(my[v] == -1)
flag = true;
else
{
dx[my[v]] = dy[v] + 1;
que.push(my[v]);
}
}
}
}
if(!flag) break;
memset(vis, 0, sizeof(vis));
for( int i = 1; i <= nx; i++)
{
if(mx[i] == -1 && dfs(i)) ans++;
}
}
return ans;
}
bool check( point a, point b)
{
if((a.x - b.x) * ( a.x - b.x) + (a.y - b.y) * (a.y - b.y) <= t*t*a.v*a.v)
return true;
return false;
}
int main()
{
int T;
scanf("%d",&T);
int ca = 1;
while(T--)
{
scanf("%d",&t);
scanf("%d",&nx);
memset(g, 0, sizeof(g));
for( int i = 1; i <= nx; i++)
{
scanf("%d %d %d",&peo[i].x, &peo[i].y, &peo[i].v);
g[i].clear();
}
scanf("%d",&ny);
for( int i = 1; i <= ny; i++)
scanf("%d %d",&umb[i].x, &umb[i].y), umb[i].v = 0;
for( int i = 1; i <= nx; i++)
for( int j = 1; j <= ny; j++)
if(check(peo[i], umb[j]))
g[i].push_back(j);
printf("Scenario #%d:\n",ca++);
int ans = solve();
printf("%d\n",ans);
printf("\n");
}
return 0;
}