[SHOI2012]回家的路
分层图,每个转弯定义为一个操作,所以建立一个上层全是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\n"); } else { printf("%lld\n", min(dis[t], dis[t + N])); } return 0; }
寻找真正的热爱