题目背景

Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。

题目描述

你现在的任务是:为Pandog寻找一条路线(有可能与主人的路线部分相同),使它能够游览最多的景点,并能够准时与主人在给定地点相遇或者汇合。

输入输出格式

输入格式:

输入文件第一行是两个整数N和M( 1≤N,M≤100 );

输入文件第二行的N个坐标给出了Grant的散步路线,即Pandog和主人相遇地点;

输入文件第三行的M个坐标给出了所有Pandog感兴趣的景点。

所有输入的坐标均不相同,且绝对值不超过1000。

输出格式:

输出小狗的移动路线。

第一行是经过的点数,第二行依次为经过的点的坐标(直角坐标系)

输入输出样例

输入样例#1: 复制

4 5
1 4 5 7 5 2 -2 4
-4 -2 3 9 1 2 -1 3 8 -3
输出样例#1: 复制

6
1 4 3 9 5 7 5 2 1 2 -2 4

说明

"The way is wrong!"表示输出方案错误(可能是坐标不存在输入文件中,两个相遇点间存在多个景点,或距离超出范围)

 题解

  我可能根本没有学过二分图……

  我们发现,当主人以直线走向下一个景点,小狗就会跑向一个景点,或者直接去与主人汇合的点

  换句话说,每一次汇合后,小狗都有两种选择,去景点,或去汇合点

  那么这两种选择很明显是不一样的,我们把它们看做二分图中的两边的点

  怎么判断某一个点是否和左边有连接呢?就看从那个汇合点到该点再到下一个汇合点的路程是否小于直接到汇合点的两倍

  然后可以先预处理出所有边,只要求出最大匹配就行了

  然后方案就是左边的点加上左边点的匹配

 //minamoto
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=;
struct node{
int x,y;
node(){}
node(int x,int y):x(x),y(y){}
}x[N],y[N];
int mp[N][N],Pre[N],vis[N];
int n,m;
double dis(node x,node y){
double a=x.x-y.x,b=x.y-y.y;
return sqrt(a*a+b*b);
}
bool dfs(int i,int tm){
for(int j=;j<n;++j)
if(vis[j]!=tm&&mp[i][j]){
vis[j]=tm;
if(!Pre[j]||dfs(Pre[j],tm)){
Pre[j]=i;return true;
}
}
return false;
}
int main(){
n=read(),m=read();
for(int i=;i<=n;++i){
int a=read(),b=read();x[i]=node(a,b);
}
for(int i=;i<=m;++i){
int a=read(),b=read();y[i]=node(a,b);
}
for(int i=;i<n;++i)
for(int j=;j<=m;++j)
if(dis(x[i],x[i+])>(dis(x[i],y[j])+dis(y[j],x[i+]))/2.0)
mp[j][i]=;
int ans=;
for(int i=;i<=m;++i){
if(dfs(i,i)) ++ans;
}
printf("%d\n",ans+n);
for(int i=;i<n;++i){
printf("%d %d ",x[i].x,x[i].y);
if(Pre[i]) printf("%d %d ",y[Pre[i]].x,y[Pre[i]].y);
}
printf("%d %d\n",x[n].x,x[n].y);
return ;
}

洛谷P2526 [SHOI2001]小狗散步(二分图匹配)的更多相关文章

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

    考虑到每次与主人相遇之前最多只去一个景点,很容易转化为匹配问题 由于数据很小,我们不妨枚举每个相遇点间隙和每个景点,判断是否来得及,如果来得及就连边 沙雕题搞了二十来分钟,我是憨憨 #include ...

  2. [P2526][SHOI2001]小狗散步

    Link: P2526 传送门 Solution: 一道提示非常到位的题目 题面中强调了在两个路径相邻点间只能再去至多一个点,且每个点只计算一次贡献 于是明显可以将原题看作询问在两个不相交点集间最多能 ...

  3. luoguP2526_[SHOI2001]小狗散步_二分图匹配

    luoguP2526_[SHOI2001]小狗散步_二分图匹配 题意: Grant喜欢带着他的小狗Pandog散步.Grant以一定的速度沿着固定路线走,该路线可能自交.Pandog喜欢游览沿途的景点 ...

  4. SHOI2001 小狗散步

    题目传送门 感觉这题最大的难点是发现它的解法是二分图最大匹配 主人的路线是固定的,对于每一段的路线,我们可以枚举小狗想去的景点,如果时间够,我们就将这段路线的起点和小狗想去的点连起来 这样就形成了一个 ...

  5. 洛谷$P1155$ 双栈排序 贪心+二分图匹配

    正解:贪心+二分图匹配 解题报告: 传送门$QwQ$ 跪了,,,我本来以为我$NOIp$做得差不多了,,,然后康了一眼发现没做多少啊其实$QAQ$ 然后来康题趴$QwQ$ 首先考虑如果只有一个栈的情况 ...

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

    传送门 简直就是模板题啊! #include <cmath> #include <cstdio> #include <cstring> #include <i ...

  7. luogu2526 [SHOI2001]小狗散步

    注意一个景点只能去一次. #include <iostream> #include <cstring> #include <cstdio> #include < ...

  8. 洛谷P2756 飞行员配对方案问题(二分图匹配)

    P2756 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其 ...

  9. 洛谷 P2756 飞行员配对方案问题 (二分图匹配)

    题目链接:P2756 飞行员配对方案问题 题意 给定 \(m\) 个外籍飞行员和 \(n - m\) 个英国飞行员,每一架飞机需要一名英国飞行员和一名外籍飞行员,求最多能派出几架飞机. 思路 最大流 ...

随机推荐

  1. [转] Linux 查找文件内容

    Linux查找文件内容的常用命令方法. 从文件内容查找匹配指定字符串的行: $ grep "被查找的字符串" 文件名例子:在当前目录里第一级文件夹中寻找包含指定字符串的.in文件g ...

  2. 【转】 Pro Android学习笔记(八一):服务(6):复杂数据Parcel

    目录(?)[-] 自定义的Parcelable类 AIDL文件 服务的实现 Client的实现 同步和异步     文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处 ...

  3. Rails、Nginx、Passenger、bundle之间的协作关系

    引自:http://www.zhihu.com/question/20062163 Bundle是Gem包的依赖管理工具,RubyGem本身有依赖管理为何还要Bundle呢?有时候两个gem虽然都依赖 ...

  4. MySQL查询某个字段为某值的次数统计SQL语句

    SELECT GoodID,sum(if(Level = 1, 1, 0)) as Better,sum(if(Level = 0, 1, 0)) as Nomal,sum(if(Level = -1 ...

  5. opencv中文网站相关下载

    http://wiki.opencv.org.cn/index.php/Download

  6. 如何判断一个字符串是否是UTF8编码

    UTF8是以8bits即1Bytes为编码的最基本单位,当然也可以有基于16bits和32bits的形式,分别称为UTF16和UTF32,但目前用得不多,而UTF8则被广泛应用在文件储存和网络传输中. ...

  7. C++实现矩阵的相加/相称/转置/求鞍点

    1.矩阵相加 两个同型矩阵做加法,就是对应的元素相加. #include<iostream> using namespace std; int main(){ int a[3][3]={{ ...

  8. webform 内置对象(页面间传值)

    QueryString/URL传值  页面名后面加?变量名=值 有点:不占服务器内存. 缺点:保密性差:传递字符串长度有限. Response   --相应请求对象 Response.Redirect ...

  9. MarkdownPad 2 安装和破解

    MarkdownPad 2 安装和破解 下载:http://markdownpad.com/ 下载下面这个: 破解:http://w3cboy.com/post/2014/10/MarkdownPad ...

  10. 本地方法中printf如何传给java--java系统级命名管道

    本地方法中printf如何传给java--java系统级命名管道 摘自:https://blog.csdn.net/dog250/article/details/6007301 2010年11月13日 ...