Returning Home(CodeForces - 1422D)

Returning Home

Yura has been walking for some time already and is planning to return home. He needs to get home as fast as possible. To do this, Yura can use the instant-movement locations around the city.

Let’s represent the city as an area of n×n square blocks. Yura needs to move from the block with coordinates (sx,sy) to the block with coordinates (fx,fy). In one minute Yura can move to any neighboring by side block; in other words, he can move in four directions. Also, there are mm instant-movement locations in the city. Their coordinates are known to you and Yura. Yura can move to an instant-movement location in no time if he is located in a block with the same coordinate x or with the same coordinate y as the location.

Help Yura to find the smallest time needed to get home.

Input

The first line contains two integers n and mm — the size of the city and the number of instant-movement locations (1≤n≤109, 0≤m≤105).

The next line contains four integers sx sy fx fy — the coordinates of Yura’s initial position and the coordinates of his home (1≤sx,sy,fx,fy≤n).

Each of the next mm lines contains two integers xi yi — coordinates of the i-th instant-movement location (1≤xi,yi≤n).

Output

In the only line print the minimum time required to get home.

Examples

Input

5 3
1 1 5 5
1 2
4 1
3 3

Output

5

Input

84 5
67 59 41 2
39 56
7 2
15 3
74 18
22 7

Output

42

Note

In the first example Yura needs to reach (5,5) from (1,1). He can do that in 5 minutes by first using the second instant-movement location (because its y coordinate is equal to Yura’s y coordinate), and then walking (4,1)→(4,2)→(4,3)→(5,3)→(5,4)→(5,5).

题意

在一个n*n大小的地图中,初始在位置 ( s x , s y ) (s_x,s_y) ,目标位置为 ( f x , f y )。每分钟可以向上下左右的地图内区域移动一格。在地图中有m个瞬移位置,当与这些位置处于同一行或同一列时,可以选择瞬间传送到该位置。求最快需要多久到达目标位置。

思路

一开始想到的是暴力建图跑最短路,但是发现那样是一个1e5的完全图肯定 不行。
那么我们把每个瞬移点拆成x点和y点两个点,最后再将这两个点之间连上一条边权为0的边即可。
对于两个瞬移点x:彼此之间距离为abs(x[i]-x[i-1]) y同理
最后跑最短路即可。

Code

#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define MOD 1000000007
#define PI 3.1415926535898
#define INF 1000055
#define MAXN 80000080
const double EPS = 1e-8;
LL read()
{
	LL x = 0, w = 1;
	char ch = 0;
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
		{
			w = -1;
		}
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return w * x;
}
LL n, m, sx, sy, ex, ey;
LL s;
LL cnt, head[INF *2], d[INF * 2];
struct node {
	LL to=0, next=0, w=0;
};
node edge[INF * 4];
void add(LL x, LL y, LL w)
{
	//cout<<x<<' '<<y<<' '<<w<<endl; 
	edge[++cnt].to = y;
	edge[cnt].next = head[x];
	edge[cnt].w = w;
	head[x] = cnt;
	edge[++cnt].to = x;
	edge[cnt].next = head[y];
	edge[cnt].w = w;
	head[y] = cnt;
}
struct nn {
	LL x, dis;
	bool operator <(const nn& b)const//重载运算符'<' 
	{
		return dis > b.dis;//顺序按照dis从小到大排(此处与sort的cmp恰好相反) 
	}
};//记录入队的节点和距离 
priority_queue < nn > q;
inline nn init(LL xx, LL dd)
{
	nn t;
	t.x = xx;
	t.dis = dd;
	return t;
}
nn now;
void dij(LL s)
{
	for (register LL i = 1; i <= INF; i++)//初始化 这里不能用m因为m可以等于0
	{
		d[i] = 0x3f3f3f3f3f;
	}
	d[s] = 0;//d[x]代表点s到 x的距离 
	now.x = s;
	now.dis = 0;
	q.push(now);
	while (!q.empty())
	{
		now = q.top();
		q.pop();
		if (now.dis > d[now.x])//优化 如果该边权大于到点now.x的距离 说明该边比已有点更差就没有必要去遍历该点了  
			continue;
		for (register LL i = head[now.x]; i != 0; i = edge[i].next)//遍历当前now点所连接的所有边 
		{
			if (d[edge[i].to] > d[now.x] + edge[i].w)//如果该边比已有点更优 则对该边所连的点进行松弛,并将该点入列 
			{
				d[edge[i].to] = d[now.x] + edge[i].w;
				q.push(init(edge[i].to, d[edge[i].to]));
			}
		}
	}
}
LL a[INF], b[INF], aa[INF], bb[INF];
bool cmp(LL xxx, LL yyy)
{
	return xxx < yyy;
}
int main()
{
	n = read();
	m = read();
	sx = read();
	sy = read();
	ex = read();
	ey = read();
	for (register LL i = 1; i <= m; i++)
	{
		a[i] = read();
		b[i] = read();
		aa[i] = a[i];
		bb[i] = b[i];
	}
	sort(a + 1, a + m + 1, cmp);
	sort(b + 1, b + m + 1, cmp);
	LL ss, ee;
	ss = m * 4 + 1;
	ee = m * 4 + 2;
	add(ss, ee, abs(sx - ex) + abs(sy - ey));
	for (register LL i = 2; i <= m; i++)
	{
		add(i, i - 1, abs(a[i] - a[i - 1]));
		add(i + m, i + m - 1, abs(b[i] - b[i - 1]));
	}
	for (register LL i = 1; i <= m; i++)
	{
		add(ss, i, abs(sx - a[i]));
		add(ss, m+i, abs(sy - b[i]));
		LL pos1 = lower_bound(a + 1, a + m + 1, aa[i]) - a;
		LL pos2 = lower_bound(b + 1, b + m + 1, bb[i]) - b;
		add(pos1, pos2 + m, 0);
		//add(ss, pos1, abs(sx - a[pos1]));
		//add(ss, pos2 + m, abs(sy - b[pos2]));
		add(ee, pos1, abs(ex - a[pos1]) + abs(ey - b[pos2]));
		//add(ee, pos2 + m, abs(ex - a[pos1]) + abs(ey - b[pos2]));
	}
	dij(ss);
	cout << d[ee] << endl;
	return 0;
}
### 回答1: 这个错误提示是指在一个返回非 void 类型的函数中没有包含 return 语句。在函数执行完毕后,应该返回一个与函数声明中指定的类型相匹配的值,否则会出现编译错误。要解决这个问题,需要在函数中添加一个 return 语句,以返回正确的值。 ### 回答2: 这个错误通常出现在函数中没有包含return语句但返回值是非空的情况下。这个问题可能导致程序无法正常工作或者崩溃。 对于一个声明有返回类型而函数体中没有包含return语句的函数,编译器会认为函数执行完成后不会有返回值。但是,如果调用该函数时确实需要返回值,那么程序就会出现问题。 解决此问题的方法很简单,只需要在函数的所有可能的代码路径上都添加return语句即可。当然,在代码的逻辑上也需要确保函数的所有执行路径上都有返回值。 例如,以下代码段声明了一个返回整数的函数,但函数体中没有包含return语句: ``` int add(int a, int b) { int sum = a + b; printf("The sum is: %d\n", sum); } ``` 要解决这个问题,只需要在函数体的末尾添加一个return语句: ``` int add(int a, int b) { int sum = a + b; printf("The sum is: %d\n", sum); return sum; } ``` 如果函数中包含多个可能的返回值,那么就需要使用条件语句来确定哪个返回语句应该被执行。 总之,no return statement in function returning non-void这个错误的出现是因为函数的返回值类型已经指定,但在函数体中缺少必要的返回语句。确保函数的所有执行路径上都有正确的返回值,就可以解决这个问题。 ### 回答3: 在编程语言中,当定义一个非空函数时,我们需要在函数的最后使用return语句来返回函数值,以让计算机知道该函数的返回值是什么。然而,如果在一个非空函数中缺失了return语句,就会引发“no return statement in function returning non-void”(非空函数缺失return语句)的错误。 这个错误一般出现于当我们定义函数时,我们会在函数头部指明该函数的返回类型(即在函数名之前的类型,例如int、float等等),但我们在函数中却没有给出return语句。这会使得编译器在编译过程中找不到该函数的返回值,从而导致编译错误。 解决该错误的方法是,在函数末尾给出return语句,并在其中返回该函数应该返回的值。如果我们在函数中定义了多个返回点(例如if...else语句块),那么我们需要保证每一个返回点都有一个对应的return语句。 此外,当我们在函数定义时使用了void关键字来表示该函数没有返回值,那么即使我们没有在函数中使用return语句,也不会出现该错误,因为编译器知道该函数没有返回值。 总之,我们需要在定义函数时清楚地指明函数的返回类型,并在函数中正确地使用return语句来避免出现“no return statement in function returning non-void”错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值