• [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;
    }
  • 相关阅读:
    luogu1131 [ZJOI2007]时态同步
    luogu1879 [USACO06NOV]玉米田Corn Fields
    luogu1345 [USACO5.4]奶牛的电信Telecowmunication
    luogu2463 [SDOI2008]Sandy的卡片
    spoj694 DISUBSTR
    luogu2852 [USACO06DEC]牛奶模式Milk Patterns
    poj2217 Secretary 后缀数组
    luogu3809 后缀排序 后缀数组
    hdu4405 Aeroplane chess
    poj2096 Collecting Bugs
  • 原文地址:https://www.cnblogs.com/newera/p/9348269.html
Copyright © 2020-2023  润新知