问题描述: 有向带权图中,求源点到另一点 X 的最短路。
迪杰斯特拉的思路:
1. 所有结点分成两类:
①确定了源点到该点的最短路的结点 (vis == true)
②没有确定源点到该点的最短路的结点 (vis == false)
2. 用 vis[i] 表示结点 i 的种类,用 dis[i] 表示源点到结点 i 的沿当前线路的距离< 在4中详细解释 '当前线路' 这个名词 >。( dis 初始成 INF ,vis 初始成 false)
用 link[i][j] 记录边 <i, j> 的权值
3. 易知,如果 i 结点为第①类结点,dis[i] 就是源点到该结点的最短路(废话)
4. 由 3 知,对于所有②类结点 J ( I 为所有①类结点),如果用 min (dis[j], dis[i] + link[i][j]) 更新 dis[j],dis[j]中最小的 dis[j0] 就是源点到 j0 的最短路。至此,j0成为①类结点。而其他的更新后的 dis,是先从源点到 i,再从 i 直接到 j 的距离,两段加在一起可不一定是源点到 j 的最短路,只能说是沿当前线路的距离。
5. 由 3, 4 知,更新不用每次枚举所有的 I, J,而只需要考虑最新加入的一个①类结点 i0 与 J 的上述关系。这是因为,除了 i0 外的关系已经在之前的更新中被更新了。
6. 最开始只有一个①类结点,源点(废话)。此时,dis[源点] = 0(又是废话)。已找到源点到结点 X 的最短路<=> X 已经是①类结点了(还是废话)。至此,可以愉快地写代码了。

#include<iostream> #include<cstdio> #include<cstring> using namespace std; int a,link[505][505]; int route[505],dis[505],minroute[505]; //route[i]为 ①类结点 i 的前驱,minroute记录最短路径 bool vis[505]; void print(int st,int end) { int p=end,l=0; while(p!=st) { minroute[++l]=p; p=route[p]; } printf("%d\n%d",dis[end],st); for(int i=l;i>=1;i--) { printf(" %d",minroute[i]); } printf("\n"); } void dijistra(int begin,int st,int end) //找到从 begin 到 end 的最短路,并记录最短路径 {//st就是最新的 ①类结点 vis[st]=1; if(st==end) //此时,已经找到了从 begin到 end的最短路 { print(begin,end); return ; } for(int i=0;i<a;i++) { if(dis[i]>link[st][i]+dis[st] && !vis[i]) //更新dis,并且记录 i结点沿当前路径的前驱 { route[i]=st; dis[i] = link[st][i] + dis[st]; } } int minpos = 10000,mid; //这里赋10000是因为题目中说边权10000代表不连通。偷个懒,不想判断连通性了 for(int i=0;i<a;i++) //找到 j0 { if(vis[i]) continue; if(dis[i]<minpos) { minpos=dis[i]; mid=i; } } if(minpos==10000) //这意味着目前所有 ②类结点的dis都大于等于10000了,它们都不与源点连通 //这说明 X 不与源点连通 { printf("NO\n"); return ; } else dijistra(begin,mid,end); //更新 i0 (代码中的 mid)与剩余 ②类结点的关系 } int main() { scanf("%d",&a); for(int i=0;i<a;i++) for(int j=0;j<a;j++) { scanf("%d",&link[i][j]); } int st,end; while(scanf("%d%d",&st,&end)==2) { if(st==-1) { return 0; } memset(vis,0,sizeof(vis)); for(int i=0;i<a;i++) dis[i]=10000; dis[st] = 0; dijistra(st,st,end); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具