1 条题解
-
0
自动搬运
来自洛谷,原作者为

Eason_AC
Remember? / AFOed on 2022.6.14 / 彻底死咯搬运于
2025-08-24 21:43:46,当前版本为作者最后更新于2019-11-02 16:26:10,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Update
- 重新修改了一些格式和 方面的问题,并修改了一些措辞,删除了一些废话。
Content
给定一个有 个点、 条边(每条边边权为 )的无向图,求从 号点到所有点的距离中:
- 最长最短路径长度最大的点的编号。
- 最长最短路径的长度。
- 有多少个点离 号点的距离为最长最短路径的长度。
数据范围:$2\leqslant n\leqslant 50000,1\leqslant m\leqslant 50000$。
Solution
可以发现这里每个边的边权是 ,所以先直接跑跑最短路就行了。
Part 1 Dijkstra+堆优化
下面的代码展示的是堆优化+ 的过程,具体思路可以自己画个图加深理解:
void dj() { memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; q.push(make_pair(0, 1)); while(!q.empty()) { int x = q.top().second; q.pop(); if(vis[x]) continue; vis[x] = 1; for(int i = h[x]; i; i = e[i].nxt) { int v = e[i].to, z = e[i].v; if(dis[v] > dis[x] + z) { dis[v] = dis[x] + z; q.push(make_pair(-dis[v], v)); } } } }多说几句写堆优化+ 要注意的:
- 一定要记得将 数组赋初值为 0x3f3f3f!(至于 vis 数组随便,因为它本来的初值都是0)
- 不要直接用
memset(dis,0x3f3f3f3f,sizeof(dis))!因为 memset 是按字节赋值的,不然你的程序会炸掉。 - 判断是否遍历该点的时候一定要将之前未标记的点标记为 !不然您的 while 循环会一直循环下去!
Part 2 正解
好了,说了这么多,接下来要讲的是处理最大最短路径的问题。
其实最大最短路径的处理也很简单,首先遍历一遍找出最大最短路径的距离,再遍历看有这个最大最短路径的点的编号是多少,最后统计出这个最大最短路径的数量就可以了,完全暴力。
Code
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <iostream> #include <queue> using namespace std; int n, m, a, b, h[100007], cnt, dis[100007], vis[100007]; struct edge { int v, to, nxt; }e[100007]; priority_queue<pair<int, int> > q; void a_e(int u, int v) { e[++cnt] = (edge){1, v, h[u]}; h[u] = cnt; e[++cnt] = (edge){1, u, h[v]}; h[v] = cnt; } void dj() { memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; q.push(make_pair(0, 1)); while(!q.empty()) { int x = q.top().second; q.pop(); if(vis[x]) continue; vis[x] = 1; for(int i = h[x]; i; i = e[i].nxt) { int v = e[i].to, z = e[i].v; if(dis[v] > dis[x] + z) { dis[v] = dis[x] + z; q.push(make_pair(-dis[v], v)); } } } } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) { scanf("%d%d", &a, &b); a_e(a, b); } dj(); int maxi = 0, ans = 0; for(int i = 1; i <= n; ++i) maxi = max(maxi, dis[i]); for(int i = 1; i <= n; ++i) if(dis[i] == maxi) { printf("%d", i); break; } printf(" %d", maxi); for(int i = 1; i <= n; ++i) if(dis[i] == maxi) ans++; printf(" %d", ans); return 0; }
- 1
信息
- ID
- 2016
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者