1003. Emergency (25)

提交情况:
这里写图片描述

#include <iostream>
#include <string.h>
using namespace std;
#define Max 510
#define INF 0x3f3f3f3f 
//Graph为邻接矩阵存储图,weight为点权,w记录最短路径上的点权之和 
int Graph[Max][Max],weight[Max],w[Max];
//visit为访问数组,为0代表未被访问
//dist记录最短的路径;num代表最短的路径的条数,初始时都为0 
int visit[Max],dist[Max],num[Max];
int n,m,c1,c2;
void Dijkstra( int start )
{
    visit[start] = 1;
    for( int i=0;i<n;++i )
    {

        int vertex = -1,min = INF;
        for( int j=0;j<n;++j)  //找到距离最短的节点 
        {
            if( visit[j] == 0 && dist[j] < min )
            {
                vertex = j;
                min = dist[j];
            }
        }
        visit[vertex] = 1;      //vertex为中介节点,通过vertex检查其它的节点 
        for( int j=0;j<n;++j )  //用找到的节点检查其它节点.其中j为需要检查的节点 
        {
            if( visit[j] == 0 && dist[vertex]+Graph[vertex][j] < dist[j] )  //找到某一条更短的路径 
            {                                                               //则更新最短路径长度和点权之和 
                dist[j] = dist[vertex]+Graph[vertex][j];                    //只要找到最短的路径就要更新点权,因为路径优先 
                w[j] = w[vertex] + weight[j];
                num[j] = num[vertex];                                       //找到新的最短路径,则数量设置为1.
                                                                            //我也不知道为什么这样写,我看的别人的代码                                                  
            }
            else if( visit[j] == 0 && dist[vertex]+Graph[vertex][j] == dist[j] ) //如果有相同的最短路径 
            {                                                                    //则更新条数和点权 
                num[j] = num[vertex]+num[j];         //我也不知道为什么这么写,我还是看的别人的代码。其余的代码都是我自己写的 
                if( w[vertex] + weight[j] > w[j] )  //如果中介节点的点权与检查节点的点权之和大于目前已知的最短路径上的点权 
                {
                    w[j] = w[vertex] + weight[j];
                }
            }
        }
    }
}
int main()
{
    cin>>n>>m>>c1>>c2;
    for(int i=0;i<n;++i)
    {
        cin>>weight[i];
        memset(Graph[i],INF,sizeof(Graph[i]));
    }   
    for(int i=0;i<m;++i)
    {
        int a,b,length;
        cin>>a>>b>>length;
        Graph[a][b] = length;
        Graph[b][a] = length;
    }
    //初始化操作 
    for( int i=0;i<n;++i )
    {
        dist[i] = Graph[c1][i];     //初始化dist数组,一开始dist数组的值对应邻接矩阵中从c1中那一行的值 
        if( Graph[c1][i] != INF  )  //如果直接有边与c1相接,则把w[i]设置为起始节点和和相接的节点的点权之和 
        {                           //因为有边相接,所以存在目前已知的最短路径,因此把num[i]设置为1 
            w[i] = weight[c1] + weight[i];   //初始化w数组
            num[i] = 1;
        } 
    }
    w[c1] = weight[c1];
    num[c2] = 1;    
    memset(visit,0,sizeof(visit));
    Dijkstra(c1);   
    cout<<num[c2]<<" "<<w[c2];
    return 0;
}

一开始我写的代码只有部分正确,只能得13分,后来加上对c1==c2(即起始节点和结束节点相同)的判断之后也只能得16分。后来怎么想也不明白哪里没有考虑到。偶尔一眼看到《算法笔记》 上的两句代码,收到启发,才知道自己错在哪里。
主要改了两处代码:
1、num[j] = 1;改为num[j] = num[vertex];、
这处改动是当检测到有更短的路径长度时,更新num[j]。num[j] = 1只是简单地讲num[j]设置为1。这样没有考虑到到达中介节点的路径条数,即:从开始节点到达vertex节点的路径条数。
当通过中介节点3进行检测时,发现通过中介节点3到达节点5的路径长度为4,比路径0-1-5长度少。此时num[3] = 2;num[5] = 1;若简单地将num[5]置为1,并符合实际情况,而应该设置为到达中介节点的路径长度,即num[5] = num[3] =2;

这里写图片描述

2、++num[j];改为num[j] = num[vertex]+num[j];
这处改动是当检测到相同的路径长度时,将num[j]进行加1操作。同样这样做并没有考虑到以前的路径的情况,即改动之后等式有边的num[j];和到达中介节点的路径条数。如下图所示:
当起始节点为0,通过中介节点3到达节点5时,与0-1-5的路径长度相同。此时num[3] = 2,num[5] = 1(即0-1-5这一条路径)。不应该简单将num[j]加1。而是num[j] = num[vertex]+num[j]=2+1=3。就是这种情况,不知道我理解的对吗?我举得例子形象生动吗?画的图清楚吗?好心累

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值