问题描述 给定一个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
这道题我使用的是Bellman Ford 算法,该算法的特点是能判断负环,题目保证没有负环,因此用dijkstra等其它最短路算法也行,这里对Bellman Ford的算法解释不详细,读者可自行去了解
代码如下:
#include <stdio.h>
#define INF 999999
struct e
{
int u, v;
int weight;
} edge[200005]; //储存图的所有边
int dis[200005];//储存到所有点的最短距离
int Bellman_Ford(int n, int m)
{
int i, j;
int flag = 1;
for (i = 1; i <= n; i++)
dis[i] = INF;//默认所有点的最短距离为无穷大
dis[1] = 0;//令第一点到第一点的距离为0
for (i = 0; i < n - 1; i++)//至多遍历n-1才能求出最短路径,n为定点数
{
flag = 1;
for (j = 0; j < m; j++)//遍历所有的边,m为边数
if (dis[edge[j].u] + edge[j].weight < dis[edge[j].v])//如果从u到v经过第j条边比原来经过的边短就从第j条边过
{
flag = 0;//这里表示如果遍历所有的边后有至少一次更新就令flag=0,说明还没求完最短路径
dis[edge[j].v] = dis[edge[j].u] + edge[j].weight;//更新最短路径
}
if (flag)//如果flag==1说明虽然还没有遍历n-1次,但已经提前选完了最短路径,可以退出了,起到优化时间的效果
break;
}
for (i = 2; i <= n; i++)//把第一点到其它所有点最短路的距离输出
printf("%d\n", dis[i]);
return 1;
}
int main()
{
int n, m;
int i;
scanf("%d%d", &n, &m);
for (i = 0; i < m; i++)
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].weight);
Bellman_Ford(n, m);
return 0;
}