[P2526][SHOI2001]小狗散步
Posted newera
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[P2526][SHOI2001]小狗散步相关的知识,希望对你有一定的参考价值。
Link:
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]小狗散步的主要内容,如果未能解决你的问题,请参考以下文章