文章目录
题目概述解法最短路径条数求取所有最短路径中,点权和的最大值求取
核心代码buglist
题目概述
给出一张图,每个节点有权值,每条边也有边权(正)。 求:
最短路的条数所有最短路径中,点权和的最大值
解法
题为单源最短路问题,本文使用了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
此题图为无向图,最开始建图的时候忘记添加双向边的代码,wa的莫名其妙