最短路径算法

 /***************************************
 * About:    有向图的Dijkstra算法实现
 * Author:   Tanky Woo
 * Blog:     www.WuTianQi.com
 ***************************************/

#include <iostream>
#include <stdio.h>

using namespace std;

const int MAX_NUM = 100;
const int INT_MAX = 999999;

// 各数组都从下标1开始
int min_cost[MAX_NUM];       // 表示当前点到源点的最短路径长度
int prev[MAX_NUM];           // 记录当前点的前一个结点
int cost[MAX_NUM][MAX_NUM];   // 记录图的两点间路径长度
int node_num, line;         // 图的结点数和路径数

// node_num -- n nodes
// start_node -- the source node
// min_cost[] -- the min_costance from the ith node to the source node
// prev[] -- the previous node of the ith node
// cost[][] -- every two nodes' min_costance
void Dijkstra(int node_num, int start_node, int *min_cost, int *prev, int cost[MAX_NUM][MAX_NUM])
{
    int i, j;
    int min;
    int next_node;
    int min_cost_sum;
    bool used[MAX_NUM];    // 判断是否已存入该点到S集合中
   
    for (i = 1; i <= node_num; i++)
    {
        min_cost[i] = cost[start_node][i];
        used[i] = 0;     // 初始都未用过该点
        if (min_cost[i] == INT_MAX)
        {
            prev[i] = 0;
        }
        else
        {
            prev[i] = start_node;
        }
    }
   
    min_cost[start_node] = 0;
    used[start_node]     = 1;

    // 依次将未放入used集合的结点中,取min_cost[]最小值的结点,放入结合used中
    // 一旦used包含了图中所有顶点,min_cost就记录了从源点到所有其他顶点之间的最短路径长度
    // 注意是从第二个节点开始,第一个为源点
    for (i = 2; i <= node_num; ++i)
    {
        min       = INT_MAX;
        next_node = start_node;
       
        // 找出当前未使用的点j的min_cost[j]最小值
        for (j = 1; j <= node_num; j++)
        {
            if((!used[j]) && (min_cost[j]<min))
            {
                next_node = j;
                min = min_cost[j];
            }
        }
       
        used[next_node] = 1;    // 表示next_node点已存入used集合中

        //printf ("%d --> %d cost = %d\n", prev[next_node], next_node, min);

        // 更新min_cost
        for (j = 1; j <= node_num; j++)
        {
            if((!used[j]) && cost[next_node][j]<INT_MAX)
            {
                min_cost_sum = min_cost[next_node] + cost[next_node][j];
                if(min_cost_sum < min_cost[j])
                {
                    min_cost[j] = min_cost_sum;
                    prev[j]     = next_node;
                }
            }
        }
    }
   
    for (i = 1; i <= node_num; i++)
    {
        printf ("%d --> %d\n", prev[i], i);
    }
   
}

// 查找从源点v到终点u的路径,并输出
void searchPath(int *prev, int start_node,  int dest_node)
{
    int route[MAX_NUM];
    int i = 1;
    int j = 0;
    int prev_node = prev[dest_node];
       
    route[i++] = dest_node;

    while (prev_node != start_node)
    {
        route[i++] = prev_node;
        prev_node = prev[prev_node];
    }
   
    route[i] = start_node;

    for (j = i; j >= 1; j--)
    {
        if(j != 1)
        {
            cout << j << " " << route[j] << " -> ";
        }
        else
        {
            cout << route[j] << endl;
        }
    }
}

int main()
{
    freopen("input.txt", "r", stdin);
    // 各数组都从下标1开始

    // 输入结点数
    cin >> node_num;
    // 输入路径数
    cin >> line;
    int p, q, len;          // 输入p, q两点及其路径长度
    int start_node;
    int end_node;
    int i, j;

    // 初始化cost[][]为INT_MAX
    for (i = 1; i <= node_num; ++i)
    {
        for (j = 1; j <= node_num; ++j)
        {
            cost[i][j] = INT_MAX;
        }
    }

    for (i = 1; i <= line; ++i) 
    {
        cin >> p >> q >> len;
        if(len < cost[p][q])       // 有重边
        {
            cost[p][q] = len;      // p指向q
            cost[q][p] = len;      // q指向p,这样表示无向图
        }
    }

    for (i = 1; i <= node_num; ++i)
    {
        min_cost[i] = INT_MAX;
    }

#if 0
    for (i = 1; i <= node_num; ++i)
    {
        for(j=1; j <= node_num; ++j)
        {
            printf("%8d", cost[i][j]);
        }
        printf("\n");
    }
#endif   

    start_node = 1;
    end_node   = node_num;   
    Dijkstra(node_num, start_node, min_cost, prev, cost);

    // 最短路径长度
    cout << "源点到最后一个顶点的最短路径长度: " << min_cost[end_node] << endl;

    // 路径
    cout << "源点到最后一个顶点的路径为: ";

    searchPath(prev, start_node, end_node);
}




input.txt
5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值