ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

PAT Advanced Level 1003 Emergency

2022-04-25 08:01:01  阅读:203  来源: 互联网

标签:PAT weight Emergency int 点权 路径 MAXV num 1003


原题传送门

1. 问题描述

2. Solution

题意
给出N个城市,M条无向边。每个城市中都有一定数目的救援小组,所有边的边权已知。现在给出起点和终点,求从起点到终点的最短路径条数及最
短路径上求援小组数目之和。如果有多条最短路径,则输出数目之和最大的。
样例解释
如图10-35所示,每个点的括号中是点权,每条边上标有边权。
从\(V_0\)号点到\(V_2\)号点最短路径的长度为2,共有两条: \(V_0\)-> \(V_2\)及 \(V_0\)-> \(V_1\)-> \(V_2\),这两条路径上的点权之和分别为2和4,因此选择较大者4。

思路
本题在求解最短距离的同时需要求解另外两个信息: 最短路径条数和最短路径上的最大点权之和。因此可以直接使用前面讲解的方法——令w[u]表示从起点s到达顶点u可以得到的最大点权之和,初始为0;令num[u]表示从起点s到达顶点u的最短路径条数,初始化时只有num[s]为1、其余num[u]均为0。接下来就可以在更新d[v]时同时更新这两个数组。
代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXV = 510;   // 最大顶点数
const int INF = 1e9;    // 无穷大

// n为顶点数,m为边数,st和ed分别为起点和终点
// G为邻接矩阵,weight为点权
// d[]记录最短距离,w[]记录最大点权之和,num[]记录最短路径条数
int n, m, st, ed, G[MAXV][MAXV], weight[MAXV];
int d[MAXV], w[MAXV], num[MAXV];
bool vis[MAXV] = {false};   // vis[i] = true表示顶点i已访问,初值均为false

void Dijkstra(int s) {  // s为起点
    fill(d, d + MAXV, INF);
    memset(num, 0, sizeof(num));
    memset(w, 0, sizeof(w));
    d[s] = 0;
    w[s] = weight[s];
    num[s] = 1;
    for (int i = 0; i < n; i++) {   // 循环n次
        int u = -1, MIN = INF;      // u使d[u]最小,MIN存放该最小的d[u]
        for (int j = 0; j < n; j++) {   // 找到未访问的顶点中d[]最小的
            if (!vis[j] && d[j] < MIN) {
                u = j;
                MIN = d[j];
            }
        }
        // 找不到小于INF的d[u],说明剩下的顶点和起点s不连通
        if (u == -1) return;
        vis[u] = true;      // 标记u为已访问
        for (int v = 0; v < n; v++) {
            // 如果v未访问 && u能到达v && 以u为中介点可以使d[v]更优
            if (!vis[v] && G[u][v] != INF) {
                if (d[u] + G[u][v] < d[v]) {  // 以u为中介点时能令d[v]变小
                    d[v] = d[u] + G[u][v];  // 覆盖d[v]
                    w[v] = w[u] + weight[v];    // 覆盖w[v]
                    num[v] = num[u];        // 覆盖num[v]
                } else if (d[u] + G[u][v] == d[v]) {    // 找到一条相同长度的路径
                    if (w[u] + weight[v] > w[v]) {  // 以u为中介点时使点权之和更大
                        w[v] = w[u] + weight[v];   // w[v]继承自w[u]
                    }
                    // 最短路径条数与点权无关,必须写在外面
                    num[v] += num[u];
                }
            }
        }
    }
}

int main() {
#ifdef ONLINE_JUDGE
#else
    freopen("./input/1003.txt", "r", stdin);
#endif
    scanf("%d%d%d%d", &n, &m, &st, &ed);
    for (int i = 0; i < n; i++) {
        scanf("%d", &weight[i]);  // 读入点权
    }
    int u, v;
    fill(G[0], G[0] + MAXV * MAXV, INF);  // 初始化图G
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        scanf("%d", &G[u][v]);  // 读入边权
        G[v][u] = G[u][v];
    }
    Dijkstra(st); // Dijkstra算法入口
    printf("%d %d\n", num[ed], w[ed]);  // 最短路径条数,最短路径中的最大点权
    return 0;
}

标签:PAT,weight,Emergency,int,点权,路径,MAXV,num,1003
来源: https://www.cnblogs.com/junstat/p/16188602.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有