蓝桥杯练习系统 ALGO-5 最短路

时间:2023-02-13 09:18:40
问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

普通的求最短路模板题,带负权值可以用spfa.
#include <cstdio>
#include <queue>
#include <iostream>
#include <memory.h>
using namespace std;
const int MAX = 200010;
struct Edge{
int u, v, w, next;
}g[MAX];


bool in_queue[MAX / 2];
int n, m, head[MAX / 2], dis[MAX / 2];


void spfa(int s){
memset(dis, 0x20, sizeof(dis));
queue<int> q;
q.push(s);
dis[s] = 0;
in_queue[s] = true;

while(!q.empty()){
int u = q.front();
q.pop();
in_queue[u] = false;

for(int next = head[u]; next != -1; next = g[next].next){
int v = g[next].v, w = g[next].w;
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
if(!in_queue[v]){
q.push(v);
in_queue[v] = true;
}
}
}
}
}

int main(int argc, char const *argv[]){
cin >> n >> m;
for(int i = 1; i <= n; ++i){
head[i] = -1;
}
for(int i = 0; i < m; ++i){
int u, v, w;
cin >> u >> v >> w;
g[i].u = u;
g[i].v = v;
g[i].w = w;
g[i].next = head[u];
head[u] = i;
}
spfa(1);
for(int i = 2; i <= n; ++i){
cout << dis[i] << endl;
}
return 0;
}