题目描述
小明是今年参加复试的外校考生,他要去民主楼小礼堂签到。由于对中南大学校本部很不熟悉,小明找到了这边读书的好朋友鲁大师,不巧,鲁大师在忙着自由探索项目的结题工作,不能给他带路,只好给他发了一份半成品的电子地图。地图上只列出了校本部内的N个点,M条路,小明处于S点,民主楼小礼堂是T点。小明感谢鲁大师,当然只是在拿到地图的一瞬间,后面的情况让他知道这半成品到底有多坑。鲁大师制作的电子地图是带有语音提示功能的,但是在编号为奇数的点他要等1分钟才能告诉他具体怎么走,而在编号为偶数的点要等2分钟。现在告诉你地图的具体情况,小明想知道他能不能在A分钟内赶到民主楼小礼堂。
输入
输入数据有多组,每组占M+1行,第一行有5个数字N,M,S,T,A,接下来M行,每行三个数字u,v,t,代表每条路的两个顶点和步行时间。(输入数据保证不含重边0<N<M<1000)
输出
对于每组输入数据,输出一行,小明能在A分钟内赶到民主楼小礼堂输出YES和最少花费的时间,否则输出KENG
样例输入
4 3 1 4 10
1 2 1
3 2 2
3 4 3
5 4 2 4 7
1 2 5
5 4 2
3 5 1
2 3 1
样例输出
YES 10
KENG
思想:最短路径(Dijkstra+优先队列)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
struct Node{
int u,d;
friend bool operator < (Node a,Node b){ //重载排序函数(从小到大)
return a.d>b.d;
}
};
const int N = 1000,INF = 1e9;
int n,m,s,T,a; //n为顶点数,m为边数,s为起点
int G[N][N],dist[N],vis[N];
void Dijkstra(int s){ //s为起点
priority_queue<Node> q;
Node node;
fill(dist,dist+n+1,INF); //初始化最短距离为INF
memset(vis,0,sizeof(vis));
dist[s] = 0; //起点s到达自身的距离为0
node.u = s,node.d = dist[s];
q.push(node); //将s入队
while(!q.empty()){ //队列不为空,即s与剩下的结点连通
node = q.top();
q.pop();
int u = node.u;
if(vis[u]) //若u已被访问过,说明当前 d并不是最小值,直接跳过
continue;
vis[u] = 1; //将u加入集合
//以u为中间结点检测剩余结点
for(int v=1;v<=n;v++){
if(!vis[v] && G[u][v]){ //如果v未访问 && u能到达v
int tmp = dist[u]+(u%2==0?2:1)+G[u][v];
if(dist[v]>tmp){ //以u为中介点可以使dist[v]更优
dist[v] = tmp; //优化dist[v]
node.u = v,node.d = dist[v];
q.push(node); //将更新的结点入队
}
}
}
}
}
int main(){
int u,v,w;
while(~scanf("%d %d %d %d %d",&n,&m,&s,&T,&a)){
memset(G,0,sizeof(G));
for(int i=0;i<m;i++){
scanf("%d %d %d",&u,&v,&w);
G[u][v] = G[v][u] = w; //有向带权图
}
Dijkstra(s);
if(dist[T]!=INF && dist[T]<=a){
printf("YES %d\n",dist[T]);
}else{
printf("KENG\n");
}
}
return 0;
}
对于29行代码的解答:
疑惑:有没有可能某个顶点u已经出队,但是在后面的操作中又入队,且这个时候的d[u]比之前出队的距离还要小,那么这个时候就应该更新与其相连的顶点,这里30行已经continue会不会有问题呢?怎么证明后面不会再有比之前已出队的d[u]小 ?
回答:当u出队以后,之后的d[u]不可能更小。因为只有当u是当前队列中d最小的结点时,才会出队,此时队列中其他的d[i]都比d[u]要大,那么假设i能到u,那样d[i] + G[i][u]也不可能比d[u]更小(因为d[u]已经是当前最小的了,而且dijkstra能解决的图边权一定要为正)
另一种求最短路径方法1009: 安全路径(做了一点改变,求最大安全系数),时间复杂度更高
本文详细解析了使用Dijkstra算法结合优先队列求解最短路径的问题,通过一个具体的例子,介绍了如何处理带权图中从起点到终点的最短路径计算,包括考虑节点等待时间的复杂情况。
3870

被折叠的 条评论
为什么被折叠?



