源点-起点 汇点-终点

迪杰斯特拉朴素版
1.初始化dist起点为0 其余点为无穷大
2.重复n次 每次找到未确定的离起点最短的点t 用t对其它点的距离进行更新
3.将点t标记为已确定

[迪杰斯特拉朴素版] [c++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<bits/stdc++.h>
using namespace std;

const int N=520;
int n,m,dist[N],g[N][N];
bool st[N];

int dj()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0; //除了起点都初始化为正无穷
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j] &&(t==-1 || dist[t]>dist[j])) //找t 即dist最小值
{
t=j;
}
}
st[t]=true;
for(int j=1;j<=n;j++)
{
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
}
if(dist[n]==0x3f3f3f3f) return -1;
else return dist[n];
}

int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);
}
int t=dj();
cout<<t<<endl;
return 0;
}


很简单 n次迭代 循环所有边 如果第n次仍松弛 说明有负权回路

[bellman-ford] [c++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <bits/stdc++.h>
using namespace std;
const int N = 510, M = 1e4 + 10;
int n, m, k;
int dist[N], back[N];
struct Edge {
int a, b, c;
} edge[M];

int bellman_ford() {
dist[1] = 0;
for (int i = 1; i <= k; i++) { //此处k 经过不超过k条边的最短路距离
memcpy(back, dist, sizeof dist);
for (int j = 1; j <= m; j++) {
int a = edge[j].a, b = edge[j].b, w = edge[j].c;
dist[b] = min(dist[b], back[a] + w);
}
}
if (dist[n] >= 0x3f3f3f3f / 2) return -0x3f3f3f3f;
return dist[n];
}

int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= m; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
edge[i] = {u, v, w};
}
memset(dist, 0x3f3f3f3f, sizeof dist);
int ans = bellman_ford();
if (ans == -0x3f3f3f3f) puts("impossible");
else printf("%d", ans);
return 0;
}