求某点到所有点的距离
给定一个 nn 个点 m 条边的有向强连通图。
点的编号为 1∼n,边的长度均为 1。
给定一条由点 ss 到点 tt 的简单路径 p1,p2,…,pk,其中 p1=s,pk=t。
注意,这条路经不一定是从点 s 到点 t 的最短路径。
现在,小明要沿着这条路径从点 s 走到点 t。
在他的行进过程中,手机上的导航软件将持续为他导航,持续为他提供最短行进线路建议。
当然,他并不一定会采纳这些建议,因为他一定会沿着之前给定的线路行进。
设想一下,在行进中,导航软件的工作过程。
首先,在点 s 处,导航软件会找到并显示出一条从点 s 到点 t 的最短路径。
如果小明的行进线路恰好与软件推荐线路一致,则软件推荐线路将不会发生任何改变。
但是,如果小明在某一点处,行进线路与软件推荐线路发生了分歧,例如,软件推荐前往点 v,小明却前往了点 w。
那么,在他到达点 w 后,软件就会实时更新推荐线路,即找到并显示出一条从点 w 到点 t 的最短路径。
导航软件会一直工作到小明到达点 t 为止,在这一过程中,软件的提供线路可能会经过若干次更新。
例如,给定一个有向强连通图,如下所示:
给出的简单路径为 [1,2,3,4](s=1,t=4)。
那么,小明从点 1 出发,导航软件找到并显示出一条从点 1 到点 4 的最短路径,这样的路径只有一条 [1,5,4]。
小明并未听从软件的建议,坚持到达了点 2,此时软件推荐线路实时更新,提供出一条点 2 到点 4 的最短路径,例如 [2,6,4](注意,软件提供的最短路径也有可能是 [2,3,4])。
小明还是不听软件的建议,坚持到达了点 3,此时软件推荐线路再次更新,提供出一条点 3 到点 4 的最短路径,即[3,4]。
最后,小明沿软件提供路线,到达目的地点 4,软件完成导航。
总的来看,软件推荐线路发生了两次更新。
值得注意的是,如果软件在第一次更新推荐线路时,给出的最短路径为 [2,3,4],则小明将按照推荐线路走到终点,软件将无需再次更新推荐线路。
也就是说,由于软件在推荐最短路径时具有随机性,所以在整个行进过程中,软件更新推荐线路的次数并不确定。
现在,给定有向图和行进路线,请你求出软件更新推荐线路的最小可能次数和最大可能次数。
输入格式
第一行包含两个整数 n 和 m。
接下来 m 行,每行包含两个整数 u,v,表示存在一条从点 u 到点 v 的有向边。
随后一行包含一个整数 k。
最后一行包含 k 个整数 p1,p2,…,pk。
输出格式
一行,空格隔开的两个整数,表示软件更新推荐路线的最小可能次数和最大可能次数。
数据范围
前三个测试点满足 1≤n≤10。
全部测试点满足 2≤n≤m≤2×10^5,1≤u,v≤n,u≠v,2≤k≤n,1≤pi≤n,pi 两两不同。
保证输入没有重边,但是可能同时存在端点相同方向不同的两条边,例如 (a,b) 和 (b,a)。
输入样例1:
6 9
1 5
5 4
1 2
2 3
3 4
4 1
2 6
6 4
4 2
4
1 2 3 4
输出样例1:
1 2
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 200010; const int M =N; int h[N], e[M], ne[M], idx; int n,m; int dist[N],cnt[N],q[N]; int path[N]; void add(int a, int b) // 添加一条边a->b { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } void bfs(int s){ int hh=0,tt=0; memset(dist, 0x3f3f3f3f, sizeof dist); dist[s]=0; q[0]=s; while(hh<=tt){ int t=q[hh++]; for(int i=h[t];~i;i=ne[i]) { int j=e[i]; if(dist[j]>dist[t]+1) { dist[j]=dist[t]+1; cnt[j]=1; q[++tt]=j; } else if(dist[j]==dist[t]+1)cnt[j]++; } } } int main() { scanf("%d%d", &n, &m); memset(h, -1, sizeof h); while (m -- ) { int a,b; scanf("%d%d", &a, &b); add(b,a); } int k; scanf("%d", &k); for (int i = 1; i <= k; i ++ ) scanf("%d", &path[i]); bfs(path[k]); // cout<<dist[1]; int minc=0,maxc=0; for(int i=1;i<k;i++){ int a=path[i]; int b=path[i+1]; /// cout<<a<<' '<<b<<endl; // cout << dist[a]<<' '<<dist[b]<<endl; if(dist[a]<dist[b]+1)minc++,maxc++; else if(cnt[a]>1)maxc++; } printf("%d %d\n",minc,maxc); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?