zoukankan      html  css  js  c++  java
  • Go Running【二分图匹配,HK】-2020杭电多校4

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=6808

    分析:

    问题可以转化为在一个平面上求最少的直线将全部的点覆盖(直线的斜率只能为 (1) 或者 (-1)),将平面旋转 (45^。),那么直线就平行于 (x)(y) 轴,对于一个点,就相当于在其横纵坐标之间连一条边,问题转化为二分图的最小顶点覆盖,求最大匹配即可。但如果直接旋转,坐标就会变成浮点数,不好处理。因此,可以转化为在 (y) 轴上的截距的匹配,注意要离散化。另外,求最大匹配不能用匈牙利算法,复杂度为:(O(n*m)),会超时,要用时间复杂度为 (O(sqrt{n}*m))(HK) 算法。用网络流处理最大匹配也可以。

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    const double pi=acos(-1);
    vector<int>pic[N<<1];
    queue<int>que;
    int cx[N],cy[N],dx[N],dy[N],a[N],b[N],d[N<<1];
    int dis,V,len;
    bool vis[N];
    int getid(int m)
    {
        return lower_bound(d+1,d+1+len,m)-d;
    }
    bool bfs()
    {
        while(!que.empty())
            que.pop();
        for(int i=1;i<=len;i++)
        {
            dx[i]=-1;
            dy[i]=-1;
        }
        dis=inf;
        for(int i=1;i<=len;i++)
        {
            if(cx[i]==-1)
            {
                que.push(i);
                dx[i]=0;
            }
        }
        while(!que.empty())
        {
            int now=que.front();
            que.pop();
            if(dx[now]>dis) break;
            for(int i=0;i<pic[now].size();i++)
            {
                int t=pic[now][i];
                if(dy[t]==-1)
                {
                    dy[t]=dx[now]+1;
                    if(cy[t]==-1) dis=dy[t];
                    else
                    {
                        dx[cy[t]]=dy[t]+1;
                        que.push(cy[t]);
                    }
                }
            }
        }
        return dis!=inf;
    }
    int dfs(int v)
    {
        for(int i=0;i<pic[v].size();i++)
        {
            int t=pic[v][i];
            if(!vis[t]&&dy[t]==dx[v]+1)
            {
                vis[t]=1;
                if(cy[t]!=-1&&dy[t]==dis) continue;
                if(cy[t]==-1||dfs(cy[t]))
                {
                    cy[t]=v;
                    cx[v]=t;
                    return true;
                }
            }
        }
        return false;
    }
    int HK()
    {
        int ans=0;
        for(int i=1;i<=len;i++)
        {
            cx[i]=-1;
            cy[i]=-1;
        }
        while(bfs())
        {
            for(int i=1;i<=len;i++)
                vis[i]=false;
            for(int i=1;i<=len;i++)
            {
                if(cx[i]==-1&&dfs(i))
                    ans++;
            }
        }
        return ans;
    }
    int main()
    {
        int t,n;
        scanf("%d",&t);
        while(t--)
        {
            int cnt=0;
            scanf("%d",&n);
            for(int i=1;i<=2*n;i++)
                pic[i].clear();
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&a[i],&b[i]);
                d[++cnt]=(a[i]+b[i]);
                d[++cnt]=(a[i]-b[i]);
            }
            sort(d+1,d+1+cnt);
            len=unique(d+1,d+1+cnt)-d-1;
            for(int i=1;i<=n;i++)
            {
                int t1=getid(a[i]+b[i]);
                int t2=getid(a[i]-b[i]);
                pic[t1].pb(t2);
            }
            printf("%d
    ",HK());
        }
        return 0;
    }
    
    
  • 相关阅读:
    mysql 索引
    redis持久化
    redis发布订阅
    django 信号
    paramiko模块
    23种设计模式python实现
    几种浏览器存储数据的方式
    关于传参
    对字符串里的四则运算进行计算2020/10/12
    动手动脑2020/10/9
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13407704.html
Copyright © 2011-2022 走看看