地铁选站

 /***************************************
 * 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 < MAX_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 < MAX_NUM; ++i)
    {
        min       = INT_MAX;
        next_node = start_node;
      
        // 找出当前未使用的点j的min_cost[j]最小值
        for (j = 1; j < MAX_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 < MAX_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 < MAX_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 << route[j] << " -> ";
        }
        else
        {
            cout << route[j] << endl;
        }
    }
}

int main()
{
    int start_node;
    int end_node;
    int i, j;
    int first_node;
    int next_node;
    int line_1[6] = {1, 2, 3, 4, 5,  6};
    int line_2[6] = {7, 8, 9, 3, 10, 15};
  
    node_num = 11;

    // init cost 1
    for (i = 0; i < MAX_NUM; ++i)
    {
        for (j = 0; j < MAX_NUM; ++j)
        {
            cost[i][j] = INT_MAX;
        }
    }
  
    // init cost 2
    for (i = 0; i < 5; i++)
    {
        first_node = line_1[i];
        next_node  = line_1[i+1];
        cost[first_node][next_node] = 1;
        cost[next_node][first_node] = 1;      
    }

    for (i = 0; i < 5; i++)
    {
        first_node = line_2[i];
        next_node  = line_2[i+1];
        cost[first_node][next_node] = 1;
        cost[next_node][first_node] = 1;
        //printf ("first_node = %d\n", first_node);
        //printf ("next_node = %d\n",  next_node);            
    }
  
    start_node = 1;
    end_node   = 7;
    // end_node or start_node does not exist ??  
    Dijkstra(node_num, start_node, min_cost, prev, cost);

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

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

    searchPath(prev, start_node, end_node);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值