算法训练 最短路
算法训练 最短路
时间限制: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 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
做的第一个最短路径问题!用的bellman算法,可以处理负边的情况。
#include <iostream> #include <cstdio> #include <cstring> #define max_v 50005 #define max_e 500005 #define INF 0x3f3f3f3f using namespace std; struct edge{int from,to,cost;}; edge ee[max_e];//存储每条边的信息 int d[max_v];//表示s到每个顶点的最短距离 int v,e;//顶点数和边数 //返回true计算最短路成功,返回false存在负圈; bool bellman(int s){ memset(d,INF,sizeof(d));//赋最大值的技巧 d[s]=0; int j=0;//添加的计数器 while(true){ bool update=false; for(int i=0;i<e;i++){ edge et=ee[i]; if(d[et.from]!=INF&&d[et.to]>d[et.from]+et.cost){ d[et.to]=d[et.from]+et.cost; update=true; } } j++; if(!update) return true; if(j==v) return false;//当进行第v次循环时,说明存在负圈 } } int main() { int x,y,z; scanf("%d %d",&v,&e); for(int i=0;i<e;i++){ scanf("%d %d %d",&x,&y,&z); x-=1; y-=1; ee[i].from=x; ee[i].to=y; ee[i].cost=z; ee[e+i].from=y; ee[e+i].to=x; ee[e+i].cost=z; } bellman(0); for(int i=1;i<v;i++){ printf("%d\n",d[i]); } return 0; }