[SHOI2001] 小狗散步 - 二分图匹配

考虑到每次与主人相遇之前最多只去一个景点,很容易转化为匹配问题

由于数据很小,我们不妨枚举每个相遇点间隙和每个景点,判断是否来得及,如果来得及就连边

沙雕题搞了二十来分钟,我是憨憨

#include <bits/stdc++.h>
using namespace std;
#define N 505
int n,m,p,cx[N],cy[N],vis[N],ax[N],ay[N],bx[N],by[N];
std::vector<int> e[N];
int dfs(int u,int Time) {
    for(int i=0;i<(int)e[u].size();++i) {
        int v=e[u][i];
        if(vis[v]^Time) {
            vis[v]=Time;
            if(!cy[v]||dfs(cy[v],Time)) {
                cx[u]=v; cy[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
double dist(double x1,double y1,double x2,double y2) {
    return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        cin>>ax[i]>>ay[i];
    }
    for(int i=1;i<=m;i++) {
        cin>>bx[i]>>by[i];
    }
    for(int i=1;i<n;i++) {
        for(int j=1;j<=m;j++) {
            if(dist(ax[i],ay[i],bx[j],by[j])+dist(ax[i+1],ay[i+1],bx[j],by[j])
               <= 2.0*dist(ax[i],ay[i],ax[i+1],ay[i+1]))
                e[i].push_back(j);
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i) ans+=dfs(i,i);
    printf("%d\n",ans+n);
    for(int i=1;i<=n;i++) {
        cout<<ax[i]<<" "<<ay[i]<<" ";
        if(cx[i]) cout<<bx[cx[i]]<<" "<<by[cx[i]]<<" ";
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12262497.html
今日推荐