7-35 城市间紧急救援

题目地址:
传送门
一道普通的单源最短路问题,加上最短路径条数和顶权,更新方式见代码
注意一个问题,不要加这句话。
在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;

const int MAXVERTEX = 510;
const int INF = 0x3f3f3f;

int n, m, s, d;

int dist[MAXVERTEX];
int finish[MAXVERTEX];
//存路径
int pre[MAXVERTEX];

//存最短路径条数
int shortRoute[MAXVERTEX];

//顶权
int peopleNum[MAXVERTEX];
//存起点到各个顶点的最多救援队数量
int sumNumber[MAXVERTEX];

//边权
int G[MAXVERTEX][MAXVERTEX];

void init();
void dijstra();
void Print(int t);

stack<int> path;
int main()
{

   //输入
   //顶点数,边数,起点终点
   cin >> n >> m >> s >> d;
   //顶权
   for (int i = 0; i < n; i++)
   {
      cin >> peopleNum[i];
   }

   for (int i = 0; i < n; i++)
   {
      for (int j = 0; j < n; j++)
      {
         G[i][j] = (i == j) ? 0 : INF;
      }
   }
   while (m--)
   {
      int u, v, w;
      cin >> u >> v >> w;
      G[u][v] = G[v][u] = w;
   }

   dijstra();
   cout << shortRoute[d] << " " << sumNumber[d] << endl;

   for (int p = pre[d]; p != s; p = pre[p])
   {
      path.push(p);
   }
   cout << s << " ";
   while (!path.empty())
   {
      cout << path.top() << " ";
      path.pop();
   }
   cout << d;

   return 0;
}

void dijstra()
{
   dist[s] = 0, shortRoute[s] = 1, sumNumber[s] = peopleNum[s];

   for (int i = 0; i < n; i++)
   {
      dist[i] = G[s][i];
   }

   for (int i = 0; i < n - 1; i++)
   {
      int min = INF, k = -1;
      for (int j = 0; j < n; j++)
      {
         if (!finish[j] && dist[j] < min)
         {
            min = dist[j], k = j;
         }
      }
      //说明这个点跟其他点不连通
      if (k == -1)
         break;

      finish[k] = 1;
      for (int j = 0; j < n; j++)
      {
         //能到达此节点并且没有被访问过
         if (G[k][j] != INF && finish[j] == 0)
         {
            if (dist[k] + G[k][j] < dist[j])
            {
               //更新边权
               dist[j] = dist[k] + G[k][j];
               //更新最短路径
               shortRoute[j] = shortRoute[k];
               //更新顶权
               sumNumber[j] = sumNumber[k] + peopleNum[j];
               //存下当前节点前驱
               pre[j] = k;
            }
            else if (dist[k] + G[k][j] == dist[j])
            {
               //更新最短路径条数
               shortRoute[j] += shortRoute[k];
               if (sumNumber[j] < sumNumber[k] + peopleNum[j])
               {
                  //更新顶权
                  sumNumber[j] = sumNumber[k] + peopleNum[j];
                  //存下当前节点前驱
                  pre[j] = k;
               }
            }
         }
      }
   }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值