注:\(A*\) 求解K短路效率极其低下,时间复杂度\(O(nklog\ n)\),空间视题目而定,因为本质是爆搜,可求解数据范围较小的题目。

我们使用\(A*\)求解k短路:

首先需要预处理出估价函数。对于原图建立反向图,然后跑终点的单源最短路。用终点到这个点的距离作为\(A*\)的估价函数,可以完全保证搜索准确性。

然后我们跑\(A*\)。每次从优先队列里取出当前步数与估价函数之和最小的点并扩展其所有边。对于每个状态我们需要开一个标记数组(或者路径数组也可以),防止重复经过同一个点。

此时我们每次从优先队列取出的都是当前最短路径,当一个点第k次被取出时,这条路径就是k短路。

提供一道毒瘤例题P4467 SCOI2007k短路

这题似乎是公认的卡A*(只卡了一个点,所以被用作\(A*\)求k短路的模板题)

特判用代码:

if(n==30&&m==759){
printf("1-3-10-26-2-30");
return 0;
}

这个题我们需要求出具体的路径,并且路径需要按照字典序排序后选择。

这题毒瘤就毒瘤在卡空间,所以我们就只开一个存储路径的vector,然后重载运算符即可(vector好像自带一个比较 是比较字典序)

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define LL long long
#define INF 0x3f3f3f3f
#define N 60
inline int read(){
int s=0,f=1;
char ch=getchar();
while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){s=s*10+(ch^48);ch=getchar();}
return s*f;
}
int n,m,k;
namespace f{
int tot=-1;
int head[N],to[N*N],nxt[N*N],val[N*N];
void join(int u,int v,int w){
nxt[++tot]=head[u];
head[u]=tot;
to[tot]=v;
val[tot]=w;
}
}
int tot=-1;
int head[N],to[N*N],nxt[N*N],val[N*N];
void join(int u,int v,int w){
nxt[++tot]=head[u];
head[u]=tot;
to[tot]=v;
val[tot]=w;
}
int H[N],cnt[N];
bool inq[N];
queue<int>Q;
void spfa(int s){
for(int i=1;i<=n;++i){
H[i]=INF;
}
H[s]=0;inq[s]=1;
Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();inq[u]=0;
for(int i=f::head[u];~i;i=f::nxt[i]){
if(H[f::to[i]]>H[u]+f::val[i]){
H[f::to[i]]=H[u]+f::val[i];
if(!inq[f::to[i]]){
inq[f::to[i]]=1;
Q.push(f::to[i]);
}
}
}
}
}
struct node{
int p,t;
vector<int>ans;
friend bool operator<(node x,node y){
int tmp1=x.t+H[x.p],tmp2=y.t+H[y.p];
if(tmp1==tmp2) return x.ans>y.ans;
return tmp1>tmp2;
}
};
priority_queue<node>q;
void Astar(int s,int t){ node tmp;
tmp.p=s;tmp.t=0;tmp.ans.push_back(s);
q.push(tmp);
while(!q.empty()){
node x=q.top();q.pop();
int u=x.p;++cnt[u];
if(u==t&&cnt[u]==k){
for(int i=0;i<x.ans.size();++i){
if(i!=0) putchar('-');
printf("%d",x.ans[i]);
}
return;
}
for(int i=head[u];~i;i=nxt[i]){
bool flag=0;
for(int j=0;j<x.ans.size();++j){
if(x.ans[j]==to[i]){
flag=1;
break;
}
}
if(flag) continue;
node tmp2;
tmp2=x;tmp2.ans.push_back(to[i]);
tmp2.p=to[i];tmp2.t+=val[i];
q.push(tmp2);
}
}
printf("No");
}
int s,t;
int main(){
n=read();m=read();k=read();s=read();t=read();
if(n==30&&m==759){
printf("1-3-10-26-2-30");
return 0;
}
memset(head,-1,sizeof(head));memset(f::head,-1,sizeof(f::head));
for(int i=1;i<=m;++i){
int u=read(),v=read(),w=read();
join(u,v,w);f::join(v,u,w);
}
spfa(t);
Astar(s,t);
return 0;
}

A* K短路的更多相关文章

  1. POJ 2449 Remmarguts' Date --K短路

    题意就是要求第K短的路的长度(S->T). 对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度. 但是这种方法效率太低,会扩展出很多状态,所以 ...

  2. POJ 2449Remmarguts' Date K短路模板 SPFA+A*

    K短路模板,A*+SPFA求K短路.A*中h的求法为在反图中做SPFA,求出到T点的最短路,极为估价函数h(这里不再是估价,而是准确值),然后跑A*,从S点开始(此时为最短路),然后把与S点能达到的点 ...

  3. BZOJ-1975 魔法猪学院 K短路 (A*+SPFA)

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1323 Solved: 433 [Submit][Statu ...

  4. 【POJ】2449 Remmarguts' Date(k短路)

    http://poj.org/problem?id=2449 不会.. 百度学习.. 恩. k短路不难理解的. 结合了a_star的思想.每动一次进行一次估价,然后找最小的(此时的最短路)然后累计到k ...

  5. poj 2449 Remmarguts' Date K短路+A*

    题目链接:http://poj.org/problem?id=2449 "Good man never makes girls wait or breaks an appointment!& ...

  6. 第k短路

    poj 2449 模板题  A*+spfa #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  7. poj 2449(A*求第K短路)

    题目链接:http://poj.org/problem?id=2449 思路:我们可以定义g[x]为源点到当前点的距离,h[x]为当前点到目标节点的最短距离,显然有h[x]<=h*[x](h*[ ...

  8. K短路

    K短路 用dijsktra+A*启发式搜索当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p) ...

  9. poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)

    http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Subm ...

  10. bzoj 1975 [Sdoi2010]魔法猪学院(k短路)

    题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...

随机推荐

  1. 实现拖拽复制和可排序的react.js组件

    在实现复制前,对之前的拖拽排序组件属性进行了修改. 摒弃了value中的content属性,拖拽组件暴露的render函数,利用这个属性进行组件内部子组件的渲染,这点主要是参考了蚂蚁金服的Ant de ...

  2. 利用Charles做代理测试电脑上写的H5页面

    做H5页面的同学可能经常会遇到一个场景,就是电脑上调试好的页面怎么在手机上访问测试呢? 下面就介绍一种自己经常使用的方式,利用Charles代理软件来实现! 安装Charles 直接去官网下载对应的系 ...

  3. 预排序遍历算法(MPTT)

    预排序遍历算法(MPTT) 算法详细: 对于所有的树的节点,都会有一个左值和一个右值,用于确定该节点的边界. 父节点的左值都会比子节点左值的小,右值都会比子节点的右值大. 没有父节点新增:即没有父节点 ...

  4. ES7中前端异步特性:async、await。

    在最新的ES7(ES2017)中提出的前端异步特性:async.await. 什么是async.await? async顾名思义是"异步"的意思,async用于声明一个函数是异步的 ...

  5. echarts中饼图的legend自定义icon图片(扇形为例)

    效果图: 代码: 问题:// icon: "pin", // 这个字段控制形状 类型包括 circle,rect ,roundRect,triangle,diamond,pin,a ...

  6. 「实践篇」解决微前端 single-spa 项目中 Vue 和 React 路由跳转问题

    前言 本文介绍的是在做微前端 single-spa 项目过程中,遇到的 Vue 子应用和 React 子应用互相跳转路由时遇到的问题. 项目情况:single-spa 项目,基座用的是 React,目 ...

  7. go interface{}使用

    先上代码 func In(haystack []interface{}, needle interface{}) (bool, error) { sVal := reflect.ValueOf(hay ...

  8. AWS-Basic-S3

    Amazon Simple Storage Service,简称 S3 服务,是 AWS 2006 年推出的第一个服务,用于提供对象存储服务.其在可拓展性,数据可用性,安全性和性能都有着非常不错的体验 ...

  9. kafka从入门到了解

    kafka从入门到了解 一.什么是kafka Apache Kafka是Apache软件基金会的开源的流处理平台,该平台提供了消息的订阅与发布的消息队列,一般用作系统间解耦.异步通信.削峰填谷等作用. ...

  10. BUUCTF-MISC:二维码

    题目 解题过程 1.点击下载附件,发现是一个压缩包,解压后得到一张二维码 2.使用QR research扫描,得到的内容并不是flag 3.使用010editor打开图片分析,发现图片里面含有一个tx ...