找到边数最少的最短路径(源和目标之间)

时间:2018-01-25 19:24:39

标签: c graph dijkstra

我正在尝试编写一个程序,该程序在图形中的两个顶点之间找到最小长度路径,从这些路径中选择一个遍历最少边缘的路径。我使用Dijkstra的算法进行了一些修改(下面)。

输出应该是:0->3->4,而是我的程序打印0->4。 为什么输出错误?

#include<stdio.h>
#include<string.h>
#define INFINITY 9999
#define n 5
#define s 0
#define d 4

void Dijkstra(int Graph[n][n], int _n,int _s, int _d);

int main()
{
    int Graph[n][n] = {
        {0, 6, 5, 1, INFINITY},
        {6, 0, 3, INFINITY, INFINITY},
        {5, 3, 0, 2, 5},
        {1, INFINITY, 2, 0, 6},
        {INFINITY, INFINITY, 5, 6, 0}
    };

    Dijkstra(Graph,n,s,d);
    getchar();
    return 0;
}

void Dijkstra(int Graph[n][n], int _n,int _s, int _d)
{
    int distance[n], parent[n], visited[n], edge[n]={0}, mindistance,
            nextnode= _s, i, j,temp[n][n], res[n];

    //parent[] stores the predecessor of each node
    //edge[] stores the number of edged of every vertex's shortest path

    for (i = 0; i < n; i++)       //create the temp matrix
        for (j = 0; j < n; j++)
            if (Graph[i][j] == INFINITY)
                temp[i][j] = INFINITY;
            else
                temp[i][j] = Graph[i][j];

    for(i=0;i<n;i++)
    {
        distance[i] = INFINITY;   //initialize distance
        parent[i] = _s;           //initialize parent
        visited[i] = 0;
        if (distance[i] > 0 && distance[i] < INFINITY)
            edge[i]++;
    }

    distance[_s] = 0;
    visited[_s] = 1;

    while (visited[_d] == 0)
    {
        //nextnode gives the node at minimum distance
        for (i = 0; i < n; i++)
        {
            mindistance = temp[_s][i] + distance[i];
            if (distance[i] < mindistance && !visited[i])
            {
                mindistance = distance[i];
                nextnode = i;
            }
        }

        //check if a better path exists through nextnode            
        visited[nextnode] = 1;

        if (nextnode != _d)
            for (i = 0; i < n; i++)
                if (!visited[i])
                {
                    if (mindistance + Graph[nextnode][i] < distance[i])
                    {
                        distance[i] = mindistance + Graph[nextnode][i];
                        parent[i] = nextnode;
                        edge[i] = edge[nextnode] + 1;
                    }

                    if (mindistance + Graph[nextnode][i] == distance[i])
                    {
                        if (edge[i] >= edge[nextnode] + 1)

                        {
                            parent[i] = nextnode;
                            edge[i] = edge[nextnode] + 1;
                        }
                    }
                }
    }

    //print the path 
    for (i = 0; i < n; i++)
        res[i] = 0;

    i = nextnode;

    while (i != _s)
    {
        res[i] = parent[i];
        i = parent[i];
    }

    printf("%d", _s);
    printf("->");
    for (i = 0; i < n; i++)
    {
        if (res[i] != 0)
        {
            printf("%d", res[i]);
            printf("->");
        }
    }
    printf("%d", _d);
}

2 个答案:

答案 0 :(得分:0)

在循环中有两个问题,您选择下一个要遍历的节点。设置

显然是不正确的
            mindistance = Graph[_s][i] + distance[i];

每次迭代,因为您需要mindistance来跟踪迭代中的最小观察距离。相反,循环之前你应该设置

        mindistance = INFINITY;

在我们查看此循环时,请注意在选择要遍历的下一个节点时忽略边缘计数标准。您也需要在此处使用该标准,以确保找到符合条件的路径。

通过这些更正,您的程序会为我生成预期的输出。

顺便说一句,请注意,这仍然是非常直接的Dijkstra。诀窍是要认识到你正在实施双组分距离测量。最重要的组件是路径长度(边缘权重之和),但边缘计数是断开连接的次要组件。因此,实现看起来有点不同,但是如果你将距离比较和设置分解为单独的函数,那么你将无法将剩余部分与标准Dijkstra(简单变体)分开。

答案 1 :(得分:0)

  

我已经编辑了我的代码,但我仍然得到了相同的错误输出:

#include<stdio.h>
#include<conio.h>

#define INFINITY 9999
#define n 5
#define s 0
#define d 4

void Dijkstra(int Graph[n][n], int _n,int _s, int _d);

int main()
{
    int Graph[n][n]={{0,6,5,1,INFINITY},{6,0,3,INFINITY,INFINITY},{5,3,0,2,5},{1,INFINITY,2,0,6},{INFINITY,INFINITY,5,6,0}};

    Dijkstra(Graph,n,s,d);
    getchar();
    return 0;
}

void Dijkstra(int Graph[n][n],int _n,int _s,int _d)
{

    int temp[n][n],distance[n],parent[n],visited[n],mindistance,nextnode,j,i;

    //parent[] stores the predecessor of each node
    //edge[] stores the number of edges in the shortest path from the source


    //create the cost matrix
    for(i=0;i<_n;i++)
        for(j=0;j<_n;j++)
                temp[i][j]=Graph[i][j];


    //initialize 
    for(i=0;i<_n;i++)
    {
        distance[i]=INFINITY;
        parent[i]=_s;
        visited[i]=0;
    }

    distance[_s]=0;
    visited[_s]=1;

    nextnode=_s;

    while(visited[_d]==0)
    {
        mindistance=INFINITY;

        //nextnode gives the node at minimum distance
        for(i=0;i<_n;i++)
        {
            distance[i]=temp[nextnode][i];
            if(distance[i]<mindistance && !visited[i])
            {
                mindistance=distance[i];
                nextnode=i;
            }
        }

            //check if a better path exists through nextnode            
            visited[nextnode]=1;
            for(i=0;i<_n;i++)
                if(!visited[i])
                    if(mindistance+temp[nextnode][i]<distance[i])
                    {
                        temp[nextnode][i]=mindistance+distance[i];
                        parent[i]=nextnode;
                    }
    }

    //print the path and distance of each node
   i=_d;
   printf("%d",i);
        do
        {

                i=parent[i];
                printf("<-%d",i);

    }while(i!=_s);
}

只需要进行一些小改动就可以得到假定的输出;我评论了下面的代码:

…
    distance[_s]=0;
//  visited[_s]=1;  do not mark the initial node as visited - will select below
//  nextnode=_s;    no need here - will select as the node at minimum distance
    while (!visited[_d])
    {
        mindistance=INFINITY;
        //nextnode gives the node at minimum distance
        for (i=0; i<_n; i++)
        {
        //  distance[i]=temp[nextnode][i];  don't change tentative distance here
            if (distance[i]<mindistance && !visited[i])
            {
                mindistance=distance[i];
                nextnode=i;
            }
        }
        //check if a better path exists through nextnode            
        visited[nextnode]=1;
        for (i=0; i<_n; i++)
            if (!visited[i])
                if (mindistance+temp[nextnode][i]<distance[i])
                {
                //  temp[nextnode][i]=mindistance+distance[i];  other way round
                    distance[i]=mindistance+temp[nextnode][i];  // smaller
                    parent[i]=nextnode;
                }
    }
…