将每个点拆分乘两个点,一个是横向的,一个是纵向的,如果这个点是站点,那么,对于这个点的横向和纵向之间连一条边权为 1 的边,然后,对于横向之间进行连边, 对于纵向之间进行连边, 但如果每个点都这样的话, 内存肯定是要炸的。 可以知道,这个题中,对我们有用的就只有各个站点和起点终点。
所以,我们要排序
#include <bits/stdc++.h>
const int maxn = 200050;
const int maxm = 10000050; //边数,往大的开
const int inf = 0x3f3f3f3f;
using namespace std;
typedef long long ll;
struct point{
int x, y;
int xu;
}p[maxn];
int b[maxn], c[maxn];
bool cmpx(int qian, int hou){ //按x排序
if(p[qian].x == p[hou].x) //x相等 y也要排个序
return p[qian].y < p[hou].y;
return p[qian].x < p[hou].x;
}
bool cmpy(int qian, int hou){ //按y排序
if (p[qian].y == p[hou].y) //y相等 x也要排个序
return p[qian].x < p[hou].x;
return p[qian].y < p[hou].y;
}
int n, m, s, t;
//1~m 横向 m+1~2m 纵向
struct note{
int to, w;
int next;
} e[maxm];
int head[maxn], cnt;
void add(int u, int v, int w){
cnt++;
e[cnt].to = v, e[cnt].w = w;
e[cnt].next = head[u], head[u] = cnt;
}
struct node{
int pos, dis;
node(){}
node(int pos1, int dis1) { pos = pos1, dis = dis1; }
bool operator<(const node& qian)const{
return qian.dis < dis;
}
};
bool vis[maxn];
int dis[maxn];
void DJ(){
for (int i = 1; i <= 2 * m; i++)
dis[i] = inf;
dis[s] = 0;
priority_queue<node> q;
q.push(node(s, 0));
while(!q.empty()){
node temp = q.top();
q.pop();
int u = temp.pos;
if(vis[u])
continue;
vis[u] = true;
for (int i = head[u]; i; i=e[i].next){
int v = e[i].to, w = e[i].w;
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
if(!vis[v])
q.push(node(v, dis[v]));
}
}
}
if(dis[t] == inf)
dis[t] = -1;
printf("%d
", dis[t]);
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++){
scanf("%d%d", &p[i].x, &p[i].y);
p[i].xu = i;
b[i] = c[i] = i;
}
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
p[++m].x = x1, p[m].y = y1, p[m].xu = m, b[m] = c[m] = m, s = m; //将起点添加进去
p[++m].x = x2, p[m].y = y2, p[m].xu = m, b[m] = c[m] = m, t = m; //将终点添加进去
sort(b + 1, b + m + 1, cmpx); //映射排序
sort(c + 1, c + m + 1, cmpy); //映射排序
for (int i = 2; i <= m; i++)
{
if (p[b[i]].x == p[b[i - 1]].x)
{ //横向之间
int u = p[b[i]].xu, v = p[b[i - 1]].xu;
int w = (p[b[i]].y - p[b[i - 1]].y) * 2; //计算权值
add(u, v, w), add(v, u, w);
}
if (p[c[i]].y == p[c[i - 1]].y)
{ //纵向之间
int u = p[c[i]].xu + m, v = p[c[i - 1]].xu + m;
int w = (p[c[i]].x - p[c[i - 1]].x) * 2; // 计算权值
add(u, v, w), add(v, u, w);
}
}
for (int i = 1; i <= m - 2; i++)
add(i, i + m, 1), add(i + m, i, 1); //一个点之间的换乘
add(s, s + m, 0), add(s + m, s, 0);
add(t, t + m, 0), add(t + m, t, 0);
DJ();
return 0;
}