[SHOI2012]回家的路

旧街凉风 提交于 2020-03-31 21:33:39

分层图,每个转弯定义为一个操作,所以建立一个上层全是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;
}

  

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!