PAT 1003 Emergency题解及buglist

题目概述

给出一张图,每个节点有权值,每条边也有边权(正)。
求:

  1. 最短路的条数
  2. 所有最短路径中,点权和的最大值

解法

题为单源最短路问题,本文使用了Dijkstra算法(才不是因为第一天做PAT,只找到之前NOIP的Dijkstra板子,复制了一下就用了)

最短路径条数求取

Dijkstra算法的核心在于松弛操作。如果要对最短路条数进行计数,只需要在松弛操作时加上技术操作即可。
设问题中起点为s;当前选中边起点为u,终点为v,权值为val;s点到i点的当前最短路径长为dist[i],s点到i点的当前最短路径有path_cnt[i]条。有如下两种更新操作:

  • 如果当前的dist[u]+val < dist[v]
    即“之前到v的路径不是最短路”。则更新dist[v]为dist[u]+val,同时更新path_cnt[v]为path_cnt[u]。“要去v当前只知道从u走过去这一条最短路,所以如果走到u共有path_cnt[u]条路的话,走到v的最短路条数也只有path_cnt[u]条路啦。
  • 如果当前的dist[u]+val == dist[v]
    即“找到了和之前最短路径长度一条最短路”。则更新操作为给新找到的最短路计数。走到u共有path_cnt[u]条路的话,新增的走到v的最短路条数就有path_cnt[u]条路啦。

所有最短路径中,点权和的最大值求取

此问题和上一个问题思路一致:在找到“更短的路径”时,更新team_cnt[e.v] = team_cnt[e.u] + a[e.v],在找到“同样短的路径”时,判断这条路径是否有更大的点权和,如果是,则更新team_cnt[e.v] = team_cnt[e.u] + a[e.v]

核心代码

dist[s] = 0; 
path_cnt[s] = 1;
team_cnt[s] = a[s];

q.push(HeapNode(s, 0));
while (!q.empty()) {
    HeapNode x = q.top(); q.pop();
    int u = x.u;
    if (done[u]) continue;
    done[u] = true;
    for (int i = 0; i < g[u].size(); i++)
    {
        Edge& e = edges[g[u][i]];
        if (dist[e.v] == dist[e.u] + e.val)
        {
            path_cnt[e.v] += path_cnt[e.u];
            if (team_cnt[e.u] + a[e.v] > team_cnt[e.v])
            {
                team_cnt[e.v] = team_cnt[e.u] + a[e.v];
            }
        }
        if (dist[e.v] > dist[e.u] + e.val) 
        {
            dist[e.v] = dist[e.u] + e.val;
            q.push(HeapNode(e.v, dist[e.v]));
            path_cnt[e.v] = path_cnt[e.u];
            team_cnt[e.v] = team_cnt[e.u] + a[e.v];
        }
    }
}

buglist

  1. 此题图为无向图,最开始建图的时候忘记添加双向边的代码,wa的莫名其妙
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章