ACM中的图中关于最短路径的dijistra算法和bellman_ford算法

dijistra算法是求从源点s开始到其他点的最短路径问题。前提条件是带权值的边。权值为正数。

1.将每个点的距离设为无穷大,彼此都不连通。将这些点的集合设为S.

2.另一个集合为V。从源点s开始,距离设为0,放到集合V中。

3.设每条边是<u,v>。则通过dist(v) = min{dis(v),dist(u) + l(u,v)} 进行松弛操作。选取最小代价的点,放到集合V中,知道集合S中的元素被拿光结束。

注意:编码时可以通过数组 visited 来对两个集合进行区分。


bellman_ford算法可以计算权值为负数。需要判断负权环。

负权环是某点存在环路,且dist值还不断减少,这样,最小值是不存在的。所以这种情况这个点是不存在最短路径的。

1.将每个点距离设为无穷大。

2.循环n-1次,n为点数。 每次循环遍历每条边,进行松弛操作 dist(v) = min{dis(v),dist(u) + l(u,v)},边是<u,v>。重复的计算知道所有边得到正确的距离代价。

3.检查负权环。如果还存在可以松弛的话,则存在负权环。此步骤相当于举反例证明最短路径不存在。

dijistra算法例子:

 The K-th City

Given a map of your country, there are N cities. The cities are labeled as 0, 1, …, N – 1, and you live in city 0. Can you calculate out the K-th nearest city form you? If two or more cities have the same distance form you, you may assume that the city with smaller label is nearer than the city with bigger one.

Input

There are several cases. The first line of each case is two integers 
N
 and 
M
 (1 ≤ 
N
 ≤ 200, 0 ≤ 
M
 ≤ 10000), which is the number of cities in your country and the total number of roads in your country. There are three integers in each of the following 
M
 lines, 
A
, 
B
, 
C
, which descript one road. 
A
 and 
B
 are the two cities that connected by that road, and 
C
 is the length of that road (1 ≤ 
C
 ≤ 2000). The roads are of both directions, and no two roads connect two same cities. There is at least one path between any two cities. At the last line of each case is a single integer 
K
 (1 ≤ 
K
 < 
N
).

The last case is followed by a line with a single 0.

Output

Print the label of the 
K
-th nearest city.

Sample Input

4 3
0 1 120
0 2 180
1 3 40
3
4 3
0 1 120
0 3 60
3 2 30
1
0

Sample Output

2
3

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define INF 0x1f1f1f1f
using namespace std;
int graph[250][250];
int distant[250];//short path
int previous[250];//record the previous nodes of the edge
int visited[250];
int m;//vertexs
int n;//edges
void Dijkstra(int k) {
    int i;
    int j;
    int l;

    for(i = 0; i < m; i ++) {
        distant[i] = INF;
    }

    distant[0] = 0;
    memset(visited, 0, sizeof(visited));
    //visited[0] = 1;


    for(i = 0; i < m; i++) {
        int mind = INF;
        int position;//short distant position
        for(j = 0; j < m; j++){
            if(!visited[j] && distant[j] < mind){
                position = j;
                mind = distant[j];
            }
        }

        if(i == k) {
            cout<<position<<endl;
            break;
        }

        visited[position] = 1;

        for(l = 0; l < m; l++) {
            if(!visited[l] && (distant[l] > distant[position] + graph[position][l])){
                distant[l] = distant[position] + graph[position][l];
            }
        }
    }
}

int main() {
    while(cin>>m && m >0) {
        cin>>n;
        int i,j;
        for(i = 0; i < m; i++){
            for(j = 0; j < m; j++){
                if(i == j) {
                    graph[i][j] = 0;
                } else {
                    graph[i][j] = INF;
                }
            }
        }

        for(i = 0; i < n; i++) {
            int from;
            int to;
            int weight;
            cin>>from>>to>>weight;
            graph[from][to] = weight;
            graph[to][from] = weight;
            //undirected graph
        }

        int k;
        cin>>k;
        Dijkstra(k);
    }
    return 0;
}

bellman_ford算法例子

TOJ 2831.   Wormholes


#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define INF 0x1f1f1f1f #define MAX 10000 using namespace std; typedef struct { int from; int to; int weight; }Edge; Edge edge[MAX]; int n;//the sum of nodes int m; int w; int sum_edge;//= 2 * m + w; int dist[MAX]; bool bellman_ford() { int i; int j; for(i = 1; i <= n; i++) { dist[i] = INF; } bool relaxation = false; for(i = 1; i < sum_edge; i++) { for(j = 1; j <= sum_edge; j++) { if(dist[edge[j].to] > dist[edge[j].from] + edge[j].weight) { dist[edge[j].to] = dist[edge[j].from] + edge[j].weight; relaxation = true; } } if(relaxation == false) break; } for(j = 1; j <= sum_edge; j++) { if(dist[edge[j].to] > dist[edge[j].from] + edge[j].weight) { return true; } } return false; } int main() { int i; int f; cin>>f; while(f--) { cin>>n>>m>>w; sum_edge = 2 * m + w; int from; int to; int weight; int num = 1; for(i = 0; i < m; i++) { cin>>from>>to>>weight; edge[num].from = from; edge[num].to = to; edge[num].weight = weight; num++; edge[num].from = to; edge[num].to = from; edge[num].weight = weight; num++; } for(i = 0; i < w; i++) { cin>>from>>to>>weight; edge[num].from = from; edge[num].to = to; edge[num].weight = - weight; num++; } if(bellman_ford()) { cout<<"YES"<<endl; } else { cout<<"NO"<<endl; } } return 0; }

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/weixin_40597170/article/details/78566204
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞