zoukankan      html  css  js  c++  java
  • HDU 2389 Rain on your Parade 最大匹配(模板题)【HK算法】

    <题目链接>

    题目大意:
    有m个宾客,n把雨伞,预计时间t后将会下大雨,告诉你每个宾客的位置和速度,每把雨伞的位置,问你最多几个宾客能够拿到伞。

    解题分析:

    本题就是要我们求人与伞之间的最大匹配,但是数据量较大,匈牙利算法复杂度为$O(n imes m)$,会超时,所以这里用的是复杂度为$O(sqrt{n} imes m)$的HK算法。

    当然,本题也可以用Dinic最大流来求解最大匹配,并且这种方法求得到最大匹配的时间复杂度也为$O(sqrt(n)*m)$

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int M = 3000+7;
    struct point{
        double x,y,s;
    }a[M],b[M];
    bool map[M][M];
    bool vis[M];
    int dx[M],dy[M];/*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号,还有就是这里就是bfs找增广路用的数组 对于u-->v可达就有dy[v] = dx[u] + 1 */
    int cx[M],cy[M];
    int dis;
    int n,T,m;
    bool searchpath()
    {
        queue<int>q;
        dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=1;i<=n;i++)
        {
            //cx[i]表示左集合i顶点所匹配的右集合的顶点序号
            if(cx[i]==-1)
            {
                //将未遍历的节点 入队 并初始化次节点距离为0
                q.push(i);
                dx[i]=0;
            }
        }
        //广度搜索增广路径
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            if(dx[u]>dis) break;
            //取右侧节点,所以用m。 
            for(int v=1;v<=m;v++)
            {
                //右侧节点的增广路径的距离 
                if(map[u][v]&&dy[v]==-1)
                {
                    dy[v]=dx[u]+1;//v对应的距离 为u对应距离加1
                    if(cy[v]==-1) dis=dy[v];
                    else
                    {
                        dx[cy[v]]=dy[v]+1;
                        q.push(cy[v]);
                    }
                }
            }
        }
        return dis!=INF;
    }
     //寻找路径 深度搜索
    int dfs(int u)
    {
        for(int v=1;v<=m;v++)
        {
            //如果该点没有被遍历过 并且距离为上一节点+1 
            if(map[u][v]&&!vis[v]&&dy[v]==dx[u]+1)
            {
                //对该点染色,即是进行标记   
                vis[v]=true;
                if(cy[v]!=-1&&dy[v]==dis)
                continue;
                if(cy[v]==-1||dfs(cy[v]))
                {
                    cx[u]=v;
                    cy[v]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
     //得到最大匹配的数目   
    int MaxMatch() 
    {
        memset(cx,-1,sizeof(cx));
        memset(cy,-1,sizeof(cy));
        int res=0;
        while(searchpath())
        {
            memset(vis,false,sizeof(vis));
            for(int i=1;i<=n;i++)
            {
                if(cx[i]==-1)
                res+=dfs(i);
            }           
        }
        return res;
    }
    int main()
    {
        int t,k=1;
        scanf("%d",&t);
        while(t--)
        {
            memset(map,false,sizeof(map));
            scanf("%d",&T);
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].s);
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            scanf("%lf%lf",&b[i].x,&b[i].y);
            for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(a[i].s*T>=sqrt((a[i].x-b[j].x)*(a[i].x-b[j].x)+(a[i].y-b[j].y)*(a[i].y-b[j].y)))
                map[i][j]=true;
            }
            int ans=MaxMatch();  
            printf("Scenario #%d:
    %d
    
    ",k++,ans);
        }
    }
    HK
  • 相关阅读:
    处理不同方向的文本1.0
    CSS盒模型
    费德曼学习法
    [转]Photoshop中的高斯模糊、高反差保留和Halcon中的rft频域分析研究
    [转]仿射变换及其变换矩阵的理解
    [转]Scintilla开源库使用指南(一
    [转]Scintilla开源库使用指南(二
    [转]C#中WinForm窗体事件的执行次序
    [转]透过IL看C#:switch语句(转)
    [转]程序员必读书单(转)
  • 原文地址:https://www.cnblogs.com/00isok/p/9955089.html
Copyright © 2011-2022 走看看