题目大意
输出一张有向带权图前k短路的长度
思路分析
这是道k短路板子题
我们可以用Astar算法来实现它
OIwiki相关算法的网页
简单来讲,Astar定义了一个估值函数f(x)=g(x)+h(x) g(x)表示由起点到达x点的路程(不一定是最短路),而h(x)则是终点到x点的最短路程
这个估值函数可以预估从该点到终点的最短路径。
在搜索中,Astar可以帮助剪枝
而在求k短路中,Astar则可以保证访问终点路径的次序与路径长度从小到大的次序相同
每次取最优f[x]进行拓展,必然可以保证较短的路径先被拓展
因此可以用Astar算法算k短路
终点被第几次访问的代价就是第几短路
代码实现方面,先从终点跑一遍单源最短路,然后从起点开始搜索,用cnt记录访问终点的次数,如果次数为k,结束搜索;如果搜索完后发现cnt不足k,再补-1输出
AC代码
#include<bits/stdc++.h>
#define N 10010
using namespace std;
struct node{int v,w;};
struct cmp{
bool operator()(node a,node b){return a.w>b.w;}
};
vector<node>g[N],rg[N];
int n,m,k,H[N];
void dijkstra(){
memset(H,0x3f,sizeof(H));
queue<int>q;
q.push(1);
H[1]=0;
while(!q.empty()){
int u=q.front();
q.pop();
for(node t:rg[u]){
if(H[t.v]>H[u]+t.w){
H[t.v]=H[u]+t.w;
q.push(t.v);
}
}
}
}
void Astar(){
priority_queue<node,vector<node>,cmp>pq;//实际上,优先队列不必要重载运算符号
pq.push({n,H[n]});
int cnt=0;
while(!pq.empty()){
node tep=pq.top();
pq.pop();
int u=tep.v,w=tep.w;
if(u==1){
cnt++;
printf("%d\n",w);
if(cnt==k)return;
}
for(auto t:g[u])pq.push({t.v,w+t.w-H[u]+H[t.v]});
}
for(;cnt<k;cnt++)printf("-1\n");
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1,u,v,d;i<=m;i++){
scanf("%d%d%d",&u,&v,&d);
g[u].push_back({v,d});
rg[v].push_back({u,d});//反向建边求以n点出发的单源最短路
}
dijkstra();
Astar();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现