题目
给定一个 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
代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 100010;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];//标记点是否在队列中
int n, m;
void add(int a, int b, int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int spfa(){
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
// 队列,存储需要被更新为较小值的点
queue<int> q;
q.push(1);
st[1] = true;
while(q.size()){
int t = q.front();//获取需要被为较小值的点
q.pop();//出队
st[t] = false;//出队之后标记其不在队列中
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];//相邻点
int we = w[i];//点t到相邻点j的边权
// 如果相邻点需要被更新,则更新1号点到t的相邻点j的最短距离
if(dist[j] > dist[t] + we){
dist[j] = dist[t] + we;
// 如果被更新的点没有在队列中,则把相邻点j添加到队列中并进行标记
if(!st[j]){
q.push(j);
st[j] = true;
}
}
}
}
return dist[n];
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
while(m --){
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
int t = spfa();
if(t == 0x3f3f3f3f) puts("impossible");
else cout << t << endl;
return 0;
}