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\n",HK());
    }
    return 0;
}

posted @ 2020-07-31 08:30  xzx9  阅读(198)  评论(0编辑  收藏  举报