7-3 城市间紧急救援(Dijkstra)

15 篇文章 0 订阅

我们采用的是优先队列形式的Dijkstra算法,具体操作和解析如下代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pi;
int maps[510][510]={0};//图的临界矩阵
int father[510];//保存最优上一级
int visit[510];//到访过了吗
int dis[510];//最优距离
int vle[510];//权值
int dpvle[510];//最优权值和
int sum[510];//种类数
int a,b,c,d;//输入值
int main()
{
    cin>>a>>b>>c>>d;
    for(int i=0;i<a;i++)cin>>vle[i];//我们输入权值
    int x,y,z;
    while(b--)//我们再输入边值
    {
        cin>>x>>y>>z;
        maps[x][y]=maps[y][x]=z;//双向的哦
    }
    for(int i=0;i<a;i++)//始初化两个数组
    {
        father[i]=-1;
        dis[i]=0x3f;
    }
    dis[c]=0;//起点距离为0
    dpvle[c]=vle[c];//起点最优权值和为该点的权值
    sum[c]=1;//最优路条数为1
    visit[c]=1;//已访问
    priority_queue<pi,vector<pi>,greater<pi>>que;//优先队列,pair排序是按第一个值排的
    for(int i=0;i<a;i++)
    {
        if(visit[i]!=1&&maps[c][i]!=0)//相当于一个始初化
        {
            dis[i]=maps[c][i];//最优距离更新
            que.push({dis[i],i});//所以我们将第一个值作为最优距离值
            father[i]=c;//出发点更新
            sum[i]=sum[c];//种类数继承
            dpvle[i]=dpvle[c]+vle[i];//最优权值为上一个点的最优权值加上这个点的权值
        }
    }
    while(!que.empty())//Dijkstra算法开始
    {
        int mdis=que.top().first;//距离
        int mnode=que.top().second;//结点
        que.pop();//出列
        if(visit[mnode]==1)continue;//已访问过直接跳过
        visit[mnode]=1;//以访问
        for(int i=0;i<a;i++)//开始筛选
        {
            if(visit[i]==0&&maps[mnode][i]!=0)//满足更新条件的前提下才可以哦
            {
                if(dis[i]>dis[mnode]+maps[mnode][i])//如果当前最优距离不是最优了就替换掉
                {   
                    dis[i]=dis[mnode]+maps[mnode][i];
                    que.push({dis[i],i});//压入队列
                    father[i]=mnode;//父亲结点更新
                    sum[i]=sum[mnode];//最优路总数继承
                    dpvle[i]=dpvle[mnode]+vle[i];//最优权值变化
                }
                else if(dis[i]==dis[mnode]+maps[mnode][i])//如果出现一样的最优情况
                {
                    sum[i]+=sum[mnode];//最短路总数增加
                    if(dpvle[i]<dpvle[mnode]+vle[i])//更新最优权值
                    {
                        dpvle[i]=dpvle[mnode]+vle[i];
                        father[i]=mnode;
                    }
                }
            }
        }
    }
    //最后就是输出过程了
    cout<<sum[d]<<" "<<dpvle[d]<<endl;
    vector<int>lo;
    int n1=d;
    lo.push_back(d);
    while(father[n1]!=-1)
    {   n1=father[n1];
        lo.push_back(n1);
    }
    int io=lo.size();
    cout<<lo[io-1];
    for(int i=io-2;i>=0;i--)cout<<' '<<lo[i];
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B程洪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值