HDU 2389(二分最大匹配优化算法,Hopcroft-Carp)
题目链接:
大致题意;
您能帮助客人在下雨之前尽可能多地找到一把雨伞?
给定所有客人的位置和跑步速度,雨伞位置,到下雨开始时的时间,找出有多少客人可
以获得一把雨伞。但两个客人不能共享一把雨伞。
输入
输入的第一行是一个整数,它是测试数据的组数。
每组测试数据的开始一行是一个到下雨开始时的时间t (1 <=t <= 5),接着的一行是客人的人数m (1 <= m <= 3000),随后有m行,每行有三个整数x、y、si,之间用空格隔开,分别表示客人的坐标(x,y)及每分钟的速度(及每分钟的速度(1 <= si <= 3000)及每分钟的速度(。客人数据描述完后的一行
上是雨伞数n(1 <= n <= 3000)及每分钟的速度(随后是n把雨伞的整数坐标,之间空一格。坐标的绝对值小于10000。
输出
对每组测试数据,一行上先输出“Scenario #i:””,其中i是测试数据的编号(从1开始)及每分钟的速度(,
随后一行上输出到下雨开始时可以获得至多一把雨伞的客人数。每一组测试数据输出后空一行。
思路:二分最大匹配优化算法,Hopcroft-Carp(原理略 )
特殊处理距离即可。
本题作用:检验模板
AC code:
#include<bits/stdc++.h>
using namespace std;
const int INF = 1 << 29;
const int maxn = 3000 + 5;
const int maxm = 3e6 + 10;
vector<vector<int> >G(maxm);
int um[maxn],vm[maxn];
int dx[maxn],dy[maxn];
int dis;
bool vis[maxn];//建立匹配关系
//bfs寻找增广路径
bool SearchP(int n){
queue<int>q;
dis = INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=1;i<=n;++i){
//u中未匹配
if(um[i]==-1){
q.push(i);
dx[i] = 0;
}
}
while(!q.empty()){
int u = q.front();q.pop();
if(dx[u]>dis) break; //说明该增广路径长度大于dis还没有结束,等待下一次BFS在扩充
for(int i=0;i<(int)G[u].size();++i){
int v = G[u][i];
if(dy[v]==-1){ //v中尚未匹配的点
dy[v] = dx[u] + 1;
//对点进行分层(不标记是匹配点和未匹配点)
if(vm[v]==-1){
//得到本次BFS的最大遍历层次
dis = dy[v];
}
else{
dx[vm[v]] = dy[v] + 1;//v是匹配点,继续延伸
q.push(vm[v]);
}
}
}
}
return (dis!=INF);
}
bool dfs(int u){
for(int i=0;i<(int)G[u].size();++i){
int v = G[u][i];
if(!vis[v]&&dy[v]==dx[u]+1){
vis[v] = 1;
if(vm[v]!=-1&&dy[v]==dis) continue;
//层次(也就是增广路径的长度)大于本次查找的dis,是searchP被break的情况,
//也就是还不确定是否是增广路径,只有等再次调用searchP()在判断。
if(vm[v]==-1||dfs(vm[v])){
vm[v] = u;
um[u] = v;
return true;
}
}
}
return false;
}
int maxmatch(int n){
int res = 0;
memset(um,-1,sizeof(um));
memset(vm,-1,sizeof(vm));
while(SearchP(n)){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;++i){
//查找到一个增广路径,匹配数++
if(um[i]==-1&&dfs(i)){
++res;
}
}
}
return res;
}
struct node1{
int x,y,s;
}pe[maxn];
struct node2{
int x,y;
}umb[maxn];
inline int getdis(const node1 &a, const node2 &b){
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
int main(){
int T,kase = 0,n,m,t;
scanf("%d",&T);
while(T--){
scanf("%d%d",&t,&m);
for(int i = 1; i <= m; ++i){
scanf("%d%d%d",&pe[i].x,&pe[i].y,&pe[i].s);
pe[i].s *= t;
pe[i].s *= pe[i].s;
}
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d%d",&umb[i].x,&umb[i].y);
}
for(int i = 0; i <= m; ++i) G[i].clear();
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j){
if(getdis(pe[i],umb[j]) <= pe[i].s){
G[i].push_back(j);
}
}
}
printf("Scenario #%d:\n%d\n\n",++kase,maxmatch(m));
}
return 0;
}