[P2526][SHOI2001]小狗散步

Posted newera

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[P2526][SHOI2001]小狗散步相关的知识,希望对你有一定的参考价值。

Link:

P2526 传送门

Solution:

一道提示非常到位的题目

题面中强调了在两个路径相邻点间只能再去至多一个点,且每个点只计算一次贡献

于是明显可以将原题看作询问在两个不相交点集间最多能连几条边

接下来将合法边连上跑二分图匹配就好了

 

Tip:二分图匹配时分清$X,Y$集合以及$match$数组是哪个集合的匹配值

Code:

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
#define X first
#define Y second
const int MAXN=105;
P a[MAXN],b[MAXN];
vector<int> G[MAXN];
int n,m,mat[MAXN],vis[MAXN],idx=1;

int dfs(int x)
{
    vis[x]=idx;
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i],m=mat[v];
        if(m==-1||vis[m]!=idx&&dfs(m))
        {mat[v]=x;return 1;}
    }
    return 0;
}

double dist(P a,P b)
{return sqrt((a.X-b.X)*(a.X-b.X)+(a.Y-b.Y)*(a.Y-b.Y));}

int main()
{
    memset(mat,-1,sizeof(mat));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].X,&a[i].Y);
    for(int i=1;i<=m;i++)
        scanf("%d%d",&b[i].X,&b[i].Y);
    for(int i=2;i<=n;i++)
    {
        double d=dist(a[i],a[i-1]);
        for(int j=1;j<=m;j++)
            if(2*d>=dist(a[i],b[j])+dist(a[i-1],b[j])) 
                G[j].push_back(i);
    }    
    
    int res=0;
    for(int i=1;i<=m;i++,idx++) res+=dfs(i);
    printf("%d
",res+n);    
    for(int i=1;i<=n;i++)
    {
        if(mat[i]!=-1) 
            printf("%d %d ",b[mat[i]].X,b[mat[i]].Y);
        printf("%d %d ",a[i].X,a[i].Y);
    }
    return 0;
}

 

以上是关于[P2526][SHOI2001]小狗散步的主要内容,如果未能解决你的问题,请参考以下文章

[luoguP2526] [SHOI2001]小狗散步(二分图最大匹配)

题解SHOI2001化工厂装箱员

排序工作量之新任务(SHOI2001)

搜索 洛谷P2530 [SHOI2001]化工厂装箱员

P2530 [SHOI2001]化工厂装箱员

洛谷P2527 [SHOI2001]Panda的烦恼