Dijkstra算法——团体程序设计天梯赛L2-001 紧急救援 (25 分)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

const int INF=0x3f3f3f3f;

int dis[502],num[502],vis[502],f[502],num1[502],path[502];
int edge[502][502];
int n,m,s,d;

void dji()//dijkstra算法
{
    dis[s]=0;//将出发地的距离记为0
    f[s]=num[s];//同理
    num1[s]=1;
    for(int i=0;i<n;i++)
    {
        int min_dis=INF,flag1=-1;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&dis[j]<min_dis)//取当前次可达最小值
            {
                flag1=j;
                min_dis=dis[j];
            }
        }
        if(flag1==-1)
            break;
        vis[flag1]=1;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&edge[flag1][j]!=INF)
            {

                if(min_dis+edge[flag1][j]<dis[j])
                {
                   dis[j]=min_dis+edge[flag1][j];
                   f[j]=num[j]+f[flag1];//救火队数量叠加
                   num1[j]=num1[flag1];//路径数量继承
                   path[j]=flag1;//路径
                }
                else if(min_dis+edge[flag1][j]==dis[j])//特判
                {
                    num1[j]+=num1[flag1];//路径数量变化
                    if(f[j]<num[j]+f[flag1])
                        {
                            f[j]=num[j]+f[flag1];
                            path[j]=flag1;
                        }
                }
            }
        }
    }
}


void printpath(int p)//输出路径
{
    if(p==s)
       {
        cout<<p;
        return ;
       }
    printpath(path[p]);
     cout<<' '<<p;//主义空格向前输出
}

int main()
{
    cin>>n>>m>>s>>d;
    memset(edge,INF,sizeof(edge));//初始化图和标记数组
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++)
        cin>>num[i];
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        edge[a][b]=c;
        edge[b][a]=c;
    }
    /*for(int i=0;i<n;i++)
        dis[i]=edge[s][i];*/
    dji();
     /*for(int i=0;i<n;i++)
        cout<<dis[i]<<' ';*/
    cout<<num1[d]<<' '<<f[d]<<endl;
    printpath(d);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值