HDU2389---Rain on your Parade (二分图匹配-HK算法)

来源:互联网 发布:mac开发网站 编辑:程序博客网 时间:2024/05/16 07:27

题目来源:https://vjudge.net/problem/HDU-2389

题意

在一个露天party里,宾客们在狂欢,还有ts时间将要下雨,现场有m个人,地上有n个雨伞,各自有着不同的坐标,人有着各自的奔跑速度,一个伞只能够容纳一个人,问, 有多少个人可以不被雨淋湿。

思路

m个人,n把伞,典型的匹配问题,只要能跑到的就说明人和该伞有关系,然后就是二分匹配,但是普通的二分匹配会超时(时间复杂度是O(VE)),所以要用到二分匹配的HK算法(同时找到多条增广轨,时间复杂度O(V^0.5*E)),来优化整个匹配过程。
比较好的博客(HK算法):
http://files.cnblogs.com/files/liuxin1.pdf

代码

#include<cmath>#include<queue>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;const double eps=1e-6;int m,n,limit;bool mp[3000+10][3000+10];bool vis[3000+10];int linkX[3000+10],linkY[3000+10];//记录该点已经被谁连接了int depthX[3000+10],depthY[3000+10];//记录下每一个点的深度struct people{    double x,y,v;} p[3000+10];struct un{    double x,y;} s[3000+10];double dis(double x,double y,double x2,double y2){    return sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));}bool seachAP(){    limit=INF;    queue<int> q;    memset(depthX,-1,sizeof(depthX));    memset(depthY,-1,sizeof(depthY));    for(int i=1; i<=m; i++)    {        if(linkX[i]==-1)//把尚未匹配的假如队列,一个一个用深度标记之后,y利用dfs一起匹配,这是优化的地方        {            q.push(i);            depthX[i]=0;        }    }    while(!q.empty())    {        int w=q.front();        q.pop();        if(depthX[w]>limit) break;//如果找到了能够匹配的,就退出,但是有人会说为啥不在找到的时候直接退出,因为要标记所有长度深度不大于limit的组合        for(int i=1; i<=n; i++)        {            if(mp[w][i]&&depthY[i]==-1)            {                depthY[i]=depthX[w]+1;                if(linkY[i]==-1)                {                    limit=depthY[i];//limit赋值                }                else                {                    depthX[linkY[i]]=depthY[i]+1;                    q.push(linkY[i]);//增广路                }            }        }    }    return limit!=INF;}bool dfs(int x){    for(int i=1; i<=n; i++)    {        if(!vis[i]&&mp[x][i]&&depthY[i]==depthX[x]+1)        {            vis[i]=1;            if(linkY[i]!=-1&&depthY[i]==limit) continue;            if(linkY[i]==-1||dfs(linkY[i]))            {                linkX[x]=i;                linkY[i]=x;                return 1;            }        }    }    return 0;}int main(){    int T,cases=1;    scanf("%d",&T);    while(T--)    {        double t;        scanf("%lf",&t);        scanf("%d",&m);        for(int i=1; i<=m; i++)        {            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].v);        }        scanf("%d",&n);        for(int i=1; i<=n; i++)        {            scanf("%lf%lf",&s[i].x,&s[i].y);        }        memset(mp,0,sizeof(mp));        for(int i=1; i<=m; i++)        {            for(int j=1; j<=n; j++)            {                double d=dis(p[i].x,p[i].y,s[j].x,s[j].y);                if(d/p[i].v-t<eps)                {                    mp[i][j]=1;                }            }        }        int res=0;        memset(linkX,-1,sizeof(linkX));        memset(linkY,-1,sizeof(linkY));        while(seachAP())        {            memset(vis,0,sizeof(vis));            for(int i=1; i<=m; i++)            {                if(linkX[i]==-1&&dfs(i))                {                    res++;                }            }        }          printf("Scenario #%d:\n",cases++);        printf("%d\n\n",res);    }}
阅读全文
0 0
原创粉丝点击