分层图,每个转弯定义为一个操作,所以建立一个上层全是x轴,下层全是y轴,两层之间连一条权值为1的边代表转弯的代价。。挺简单的其实
https://www.luogu.com.cn/problem/P3831
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
const int INF = 1e17 + 11;
const int maxn = 3e5 + 333;
const int N = 1e5 + 11;
ll dis[maxn];
int vis[maxn];
struct Node {
int p;
ll len;
int nxt;
}G[maxn * 2];
int z;
int head[maxn];
void add(int be, int en, ll len) {
G[++z].p = en;
G[z].nxt = head[be];
G[z].len = len;
head[be] = z;
}
bool operator <(const Node a, const Node b) {
return a.len > b.len;
}
void dij(int be) {
for (int i = 0; i < maxn; i++) {
vis[i] = 0;
dis[i] = 1e17;
}
dis[be] = 0;
priority_queue<Node>que;
Node ccc;
ccc.len = 0;
ccc.p = be;
que.push(ccc);
while (que.size()) {
Node cn = que.top();
que.pop();
if (vis[cn.p]) continue;
vis[cn.p] = 1;
for (int i = head[cn.p]; i; i = G[i].nxt) {
int p = G[i].p;
if (dis[p] > dis[cn.p] + G[i].len) {
dis[p] = dis[cn.p] + G[i].len;
Node ccc;
ccc.len = dis[p];
ccc.p = p;
que.push(ccc);
}
}
}
return ;
}
struct cn {
int x, y, id;
}que[maxn];
bool cp1(cn a, cn b) {
if (a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
bool cp2(cn a, cn b) {
if (a.y == b.y) return a.x < b.x;
return a.y < b.y;
}
int n, m;
int main() {
scanf("%d%d", &n, &m);
int s = m;
int t = m+1;
int x,y;
for (int i = 0; i < m; i++) {
scanf("%d%d", &que[i].x, &que[i].y);
que[i].id = i;
}
scanf("%d%d", &que[s].x, &que[s].y);
scanf("%d%d", &que[t].x, &que[t].y);
que[s].id = s;
que[t].id = t;
int len = m + 2;
sort(que, que + len, cp1);
for (int i = 1; i < len; i++) {
if (que[i - 1].x == que[i].x) {
ll ln = que[i].y - que[i - 1].y;
int be = que[i - 1].id;
int en = que[i].id;
add(be, en, 2 * ln);
add(en, be, 2 * ln);
}
}
sort(que, que + len, cp2);
for (int i = 1; i < len; i++) {
if (que[i - 1].y == que[i].y) {
ll ln = que[i].x - que[i-1].x;
int be = que[i - 1].id;
int en = que[i].id;
add(be+N, en+N, 2*ln);
add(en+N, be+N, 2*ln);
}
}
for (int i = 0; i < m; i++) {
add(i, i + N, 1);
add(i + N, i, 1);
}
add(s, s + N, 0);
add(s + N, s, 0);
add(t, t + N, 0);
add(t + N, t, 0);
dij(s);
if (dis[t] >= 1e13 ) {
printf("-1
");
}
else {
printf("%lld
", min(dis[t], dis[t + N]));
}
return 0;
}