算法训练 最短路
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个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,保证从任意顶点都能到达其他所有顶点。
第一次接触接触到求带负边的最短路,显然之前的Dijkstra和Floyd都不能解决,接触到了SPFA算法...准备把之前的最短路题用SPFA写一遍试试...
Code:
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<list>
#define mod 998244353
#define INF 0x3f3f3f3f
#define Min 0xc0c0c0c0
#define mst(a) memset(a,0,sizeof(a))
#define f(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef long long ll;
static const int MAX_N = 2e6 + 5;
static const double pi = acos(-1);
typedef struct XNode{
int dot, weight; //点,边权
struct XNode *next; //下一个可达点
}Node; //邻接表
Node *nods[MAX_N]; //任意点的下一个可达点
int dis[MAX_N];
bool vis[MAX_N];
int n, m;
void init(int u, int v, int w){
Node *p;
p = (Node *)malloc(sizeof(Node));//动态数组
p ->dot = v;
p ->weight = w;
p ->next = nods[u]; //nods是一个指向Node类型结构体的指针数组
nods[u] = p; //这里意思就是nod[u]指向u的一个可达点(p是一个中间指针)
}
void spfa(){
for(int i = 1; i <= n; i++){ //初始化
vis[i] = false;
dis[i] = INF;
}
dis[1] = 0;
vis[1] = true;
Node *p;
int u, v, w;
queue<int>q; //队列优化
q.push(1); //起始点是1
while(!q.empty()){
u = q.front();
q.pop();
vis[u] = false;
for(p = nods[u]; p != NULL; p = p ->next){
v = p ->dot;
w = p ->weight;
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
if(n == 0 && m == 0) break;
memset(nods, NULL, sizeof(nods)); //指针数组初始化
int u, v, w;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &u, &v, &w);
init(u, v, w);
}
spfa();
for(int i = 2; i <= n; i++){ //1到2,3...n的最短路
printf("%d\n", dis[i]);
}
}
return 0;
}