PAT1003

题目大意

地图中一些道路连接多个分散的城市,每个城市有若干个救援队,给定起点与终点,问从起点到终点最短路的条数,以及在所有最短路中可以集结的最大救援队数目。

输入规格

第一行包含四个整数,N(N≤500)-城市数目,M-道路数量,C1-所在城市,C2-目标城市。下一行包含N个整数,即每个城市中救援队的个数。接下来的M行为道路描述,前两个整数为城市编号,后一个整数为道路长度。

输出规格

一行打印两个数字,最短路数目以及最大救援队数目。数字由一个空格分离,行末无空格。

样例输入

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

样例输出

2 4

解题思路

使用改进的dijkstra算法。

对于最短路条数,增加num数组,当寻找到更短边更新dis数组时,由于与上一个节点直接连接,新节点的最短路条数与更新后其上一个顶点的最短路条数相同;当寻找到与原dis数组长度相同的情况时,由于在新节点上总体为两条路,因此新节点最短路条数等于新节点最短路条数与其相等距离的路线的最近节点之和。

对于最大救援队数目,增加w数组,当寻找到更短边更新dis数组时,由于仍然是同一条路径的延续,新节点w的值为上一个节点的w值与新节点点权值之和;当寻找到与原dis数组长度相同的情况时,由于找到新的路径,新节点的w值为其自身的w值与另一条路节点的值与新节点点权值之和的最大值。

关键代码(算法改动后的代码)

     

if (d[i] > d[v] + map[v][i]) {
    d[i] = map[v][i] + d[v];
    num[i] = num[v];
    w[i] = w[v] + weight[i];
}
else if (d[i] == d[v] + map[v][i]) {
    num[i] += num[v];
    w[i] = max(w[i], w[v] + weight[i]);
}

 

全部代码

    

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 500;
 6 int d[maxn + 1];
 7 int weight[maxn + 1], num[maxn + 1], w[maxn + 1];
 8 int vis[maxn + 1];
 9 int map[maxn + 1][maxn + 1];
10 int n, m, c1, c2;
11 int INF = 0x3f3f3f3f;
12 
13 void dijkstra()
14 {
15     for (int i = 0; i < n; i++)
16     {
17         vis[i] = 0;
18         d[i] = INF;
19     }
20     d[c1] = 0;
21     num[c1] = 1;
22     w[c1] = weight[c1];
23     while (1)
24     {
25         int mina = INF, v = -1;
26         for (int i = 0; i < n; i++)
27         {
28             if (!vis[i] && d[i] < mina)
29             {
30                 v = i;
31                 mina = d[i];
32             }
33         }
34         if (v == -1) break;
35         vis[v] = 1;
36         for (int i = 0; i < n; i++)
37         {
38             if (!vis[i] && map[v][i] != INF) {
39                 if (d[i] > d[v] + map[v][i]) {
40                     d[i] = map[v][i] + d[v];
41                     num[i] = num[v];
42                     w[i] = w[v] + weight[i];
43                 }
44                 else if (d[i] == d[v] + map[v][i]) {
45                     num[i] += num[v];
46                     w[i] = max(w[i], w[v] + weight[i]);
47                 }
48             }
49         }
50     }
51 }
52 int main()
53 {
54     cin >> n >> m >> c1 >> c2;
55     for (int i = 0; i < n; i++){
56         for (int j = 0; j < n; j++){
57             map[i][j] = INF;
58         }
59     }
60     for (int i = 0; i < n; i++) cin >> weight[i];
61     for (int i = 1; i <= m; i++){
62         int x, y, temp;
63         cin >> x >> y >> temp;
64         map[x][y] = map[y][x] = temp;
65     }
66     dijkstra();
67     cout << num[c2] << ' ' << w[c2];
68     return 0;
69 }

 

转载于:https://www.cnblogs.com/komorabi/p/11200181.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值