首页 > 其他分享 >T278162 最短路 (spfa+分层图)

T278162 最短路 (spfa+分层图)

时间:2022-10-14 19:36:09浏览次数:58  
标签:int 短路 路径 样例 vis spfa T278162 第四层 边权

image
(没穿红色的可莉......)

题目描述

给定一张 \(n\) 个点 \(m\) 条边的连通图,每条边有权值 \(w\) ,定义从 \(u_1\) 到 \(u_x\) 经过边 \(e_1,e_2,…,e_k\) 的路径长度为:

请分别对于每个点 \(i∈[2,n]\) 求出点 \(1\) 到 \(i\) 的长度最小的路径。

输入格式

第一行两个数,代表 \(n,m\)。

接下来 \(m\) 行每行三个数 \(u,v,w\),代表一条连接 \(u,v\) 长度为 \(w\) 的边。

输出格式

对于每个 \(i\) 输出点 \(1\) 到 \(i\) 长度最小的路径的长度,用空格分隔。

样例 #1

样例输入 #1

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

样例输出 #1

1 2 2 4

提示

【样例解释】

  • 当 \(i=2\) 时经过路径 \(1→2\)
  • 当 \(i=3\) 时经过路径 \(1→2→3\)
  • 当 \(i=4\) 时经过路径 \(1→2→4\)
  • 当 \(i=5\) 时经过路径 \(1→3→5\)

【数据范围】

对于 \(30\%\) 的数据,\(1≤n≤1000\)

对于另 \(30\%\)的数据,\(m=n-1\)

对于 \(100\%\) 的数据,\(1≤n,m≤1×10^5;0≤w_i≤10^9\)

解析

对于题干中的路径长度定义我们可以这样理解:将最长边的边权变为0,最短边的边权变成两倍,相当于有两次操作(对于一条路径有且仅能有这两个操作),我们可以用分层图的思想(一共建4层),首先每层都由x向y连z的无向边,第一层向第二层连边权为0的边,再向第三层连2倍边权的边,第二层向第四层连2倍边权,第三层向第四层连0边(巧妙的建图方法)对于一种操作向上连边,这样保证第四层都是有两次操作的,其实2.3层相当于是一个过渡,最后的答案就是第一层和第四层的d[]取min,那么答案为什么是这个呢?因为1->i可能直接相连,那么答案就是在第一层中找(只有一条边不可能还进行两次操作),答案统计过程包含了对该种情况的特判。求d[]用最短路算法就行了,我这里用的spfa。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int n, m, tot, head[N], to[N << 3], nxt[N << 3], w[N << 3], d[N];
bool vis[N];
void add(int x, int y, int z) {
	nxt[++ tot] = head[x]; head[x] = tot; to[tot] = y; w[tot] = z;
}
void spfa() {
	memset(d, 0x3f, sizeof d);
	queue<int> q;
	d[1] = 0, q.push(1); vis[1] = 1;
	while (!q.empty()) {
		int u = q.front(); q.pop(); vis[u] = 0;
		for (int i = head[u]; i; i = nxt[i]) {
			int v = to[i];
			if (d[v] > d[u] + w[i]) {
				d[v] = d[u] + w[i];
				if (!vis[v]) {
					vis[v] = 1;
					q.push(v);
				}
			}
		}
	}
}
signed main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i ++) {
		int u, v, w; cin >> u >> v >> w;
		for (int i = 0; i <= 3; i ++) {
			add(u + i * n, v + i * n, w);
			add(v + i * n, u + i * n, w);
		}
		add(u, v + n, 0), add(v, u + n, 0);
		add(u, v + 2 * n, 2 * w), add(v, u + 2 * n, 2 * w);
		add(u + n, v + 3 * n, 2 * w), add(v + n, u + 3 * n, 2 * w);
		add(u + 2 * n, v + 3 * n, 0), add(v + 2 * n, u + 3 * n, 0);
	}
	spfa();
	for (int i = 2; i <= n; i ++) {
		int ans = min(d[i], d[i + 3 * n]);
		printf("%lld ", ans); 
	}
	return 0;
}

image

标签:int,短路,路径,样例,vis,spfa,T278162,第四层,边权
From: https://www.cnblogs.com/YHxo/p/16792745.html

相关文章

  • TZOJ 1693:银牛派对(最短路/dijstra)
    描述 N个农场(1≤ N ≤1000)中的每一个都有一头奶牛,编号为1.. N将参加在农场# X(1≤ X ≤ N)举行的大型奶牛聚会。总共有M (1≤ M ≤100,000)条单向(单向......
  • 二修最短路
    观看前提示:本人的码风可能会引起您的不适。写作时间:2022-9-10~2022-10-12.1.Floyd全源最短路1-1朴素弗洛伊德,枚举每个点然后进行松弛,这样可以在\(\Theta(n^{3})\)时......
  • TZOJ 7685: 最短路径 (dijstra/输出路径pre)
    描述  给定n个顶点的带权有向图,若从顶点x到顶点y之间存在一条路径,那么这条路径的长度定义为路径上各条边的权值之和。现在请你找出从顶点1到顶点n的一条最短路径。......
  • 图论-最短路算法
    一、floyd1.介绍 floyd算法只有五行代码,代码简单,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3),可以求多源最短路问题。 2.思想: Floyd算法的基本思想如......
  • 洛谷 P2387 [NOI2014] 魔法森林 题解【动态加点 SPFA】
    题目大意给定一个由\(n\)个点\(m\)条边的无向图,每条边有权值\((a,b)\),求一条路径使这条路径上的\((a_{\max}+b_{\max})\)最小。思路正解应该是LCT动态维护MST......
  • SPFA算法思想简述
    首先定义数组\(d_i\)表示起点到\(i\)的距离(除起点外初始化为最大值),并维护一个队列。初始将起点入队,然后每一次取队头\(x\)并且松弛所有与\(x\)相连的边,同时如果能......
  • 平面图最小割转换为对偶图最短路问题
    1、P4001[ICPC-Beijing2006]狼抓兔子 P4001[ICPC-Beijing2006]狼抓兔子-洛谷|计算机科学教育新生态(luogu.com.cn)直接上图,  注意dijkstra!!!  判重......
  • 最短路径问题---Dijkstra算法详解
    0.最短路径问题介绍问题解释:从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径1.Dijkstra算法介绍算法特点:迪科斯彻算法使用......
  • 图论最短路径问题(一)
     图的基本概念总概念:图论中的图是由若干给定的点及连接两点的线构成的图形,表示事物之间的特定关系点:表示事物线:表示相应两个事物之间具有某种的特定关系数学语言描述:G(V(G)......
  • TZOJ 2674: 一个人的旅行 最短路/Floyd
    描述虽然草儿是个路痴(就是在tzc待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看......