題意:有n個人的座標和速度,有m個傘的座標,問有多少人能在t秒內到傘底下,一個傘底下只能有一個人。
思路:二分匹配,用匈牙利算法無限超時,又改用鄰接表還是超時,最後查資料才知道處理數據較大的二分匹配需要用Hopcroft-Carp算法。
Hopcroft-Carp算法模板:
/* *********************************************
二分圖匹配(Hopcroft-Carp的算法)。
初始化:g[][]鄰接矩陣
調用:res=MaxMatch(); Nx,Ny要初始化!!!
時間複雜大爲 O(V^0.5 E)
適用於數據較大的二分匹配
需要queue頭文件
********************************************** */
const int MAXN=3100;
const int INF=0x3f3f3f3f;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP()
{
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0;i<Nx;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;
for(int v=0;v<Ny;v++)
if(g[u][v]&&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)
{
for(int v=0;v<Ny;v++)
if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
{
vst[v]=1;
if(My[v]!=-1&&dy[v]==dis) continue;
if(My[v]==-1||DFS(My[v]))
{
My[v]=u;
Mx[u]=v;
return 1;
}
}
return 0;
}
int MaxMatch()
{
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP())
{
memset(vst,0,sizeof(vst));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1&&DFS(i))
res++;
}
return res;
}
//**************************************************************************/
題解:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;
/* *********************************************
二分圖匹配(Hopcroft-Carp的算法)。
初始化:g[][]鄰接矩陣
調用:res=MaxMatch(); Nx,Ny要初始化!!!
時間複雜大爲 O(V^0.5 E)
適用於數據較大的二分匹配
需要queue頭文件
********************************************** */
const int MAXN=3100;
const int INF=0x3f3f3f3f;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP()
{
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0;i<Nx;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;
for(int v=0;v<Ny;v++)
if(g[u][v]&&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)
{
for(int v=0;v<Ny;v++)
if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
{
vst[v]=1;
if(My[v]!=-1&&dy[v]==dis) continue;
if(My[v]==-1||DFS(My[v]))
{
My[v]=u;
Mx[u]=v;
return 1;
}
}
return 0;
}
int MaxMatch()
{
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP())
{
memset(vst,0,sizeof(vst));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1&&DFS(i))
res++;
}
return res;
}
//**************************************************************************/
int t;
struct node{
int x, y, s;
}peo[MAXN];
struct node1{
int x,y;
}ubl[MAXN];
int Dis(node a, node1 b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main(void)
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T, cas=1;
scanf("%d", &T);
while(T--)
{
int n,m;
memset(g, 0, sizeof(g));
scanf("%d", &t);
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d %d %d", &peo[i].x, &peo[i].y, &peo[i].s);
scanf("%d", &m);
for (int i = 0; i < m; i++)
scanf("%d %d", &ubl[i].x, &ubl[i].y);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (Dis(peo[i], ubl[j])<=peo[i].s*peo[i].s*t*t)
g[i][j]=1;
Nx = n;
Ny = m;
printf("Scenario #%d:\n%d\n\n", cas++, MaxMatch());
}
return 0;
}