给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 impossible。
数据保证不存在负权回路。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 impossible。
数据范围
1≤n,m≤105,
图中涉及边长绝对值均不超过 10000。
输入样例:
3 3
1 2 5
2 3 -3
1 3 4
输出样例:
2
//spfa算法
#include<stdio.h>
#include<string.h>
#define N 100010
#define INF 0x3f3f3f3f
int h[N], e[N], w[N], ne[N], idx;//邻接表法
int st[N], dist[N]; //dist保存到第n条边的距离,st表示的是当前结点是否在队列中
int q[N], tt, hh;//队列
int m, n;
void add(int a, int b, int c) //存储图
{
if (a != b)
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int spfa()
{
tt = -1, hh = 0; //初始化队列
memset(dist, INF, sizeof dist); //初始化距离
q[++tt] = 1; //将第一个结点入队
st[1] = 1; //此时第一个结点已在队列中
dist[1] = 0; //第一个结点到第一个结点的距离为0
while (tt >= hh) //判断队列是否为空
{
int t = q[hh++]; //让队列中的元素出队
st[t] = 0; //此时该结点不在队列中
for (int i = h[t]; i != -1; i = ne[i]) //依次遍历该结点的所有出边
{
int j = e[i]; //找到与出队的结点相连的边
if (dist[j] > dist[t] + w[i]) //判断直接到达j结点短还是从另一条路短
{
dist[j] = dist[t] + w[i]; //然后更新到j的距离
if (!st[j]) //如果队列中没有该结点就入队
{
q[++tt] = j;
st[j] = 1;
}
}
}
}
return dist[n];
}
int main()
{
memset(h, -1, sizeof(h)); //初始化邻接表
scanf("%d%d", &n, &m);
while (m--) //邻接表的赋值
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
int t = spfa();
if (t == INF)printf("impossible");
else printf("%d", t);
return 0;
}