注:\(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. .Net Core:Docker无法拉取mcr.microsoft.com相关镜像解决办法

    今天在教同事Docker简单部署Asp.Net Core项目,pull镜像时突然出现下图中的错误: 因为微软在 2018 年五月之后,只会将相关镜像打包发布到 MCR 上.但是 MCR 对国内用户不太 ...

  2. AS的不同布局

    AndroidStudio里面支持的布局有挺多种的,但是最最重要的是RelativeLayout(相对布局)和LinearLayout(线性布局),熟练掌握这两种布局也非常够用了,当然还有FrameL ...

  3. Android点击按钮退出程序并提醒

    效果展示: MainActivity.java import androidx.appcompat.app.AppCompatActivity; import android.app.AlertDia ...

  4. vue日历(纯 js,没用任何插件和组件)

    效果图: 代码:   <template> <div class="calender"> <div class="top"> ...

  5. pytest-mark 参数化

    在类前或用例前用pytest.mark.parametrize ,可进行参数化 传参方式比较灵活,有很多种,下面是列出的几种方式,其他的可自行研究 @pytest.mark.parametrize(& ...

  6. Django框架中settings.py注释

    1 # coding:utf8 2 """ 3 Django settings for DjangoTest project. 4 5 Generated by 'dja ...

  7. JavaScript 数组(Array)对象的方法

    JavaScript 数组(Array)对象的方法 concat() 描述:用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 原型:arrayObject.conc ...

  8. python---冒泡排序的实现

    冒泡排序 思想 ​ 列表中有n个数, 每两个相邻的数, 如果前边的数比后边的数大, 就交换. ​ 关键点: ​ 趟: 总共执行 n-1趟 ​ 无序区: 第 i 趟时, 索引 0~ n-1-i 为无序区 ...

  9. python版本共存与语法的注释

    python的多种版本共存 首先还是先下载python解释器除最高版本的另外两个版本 个人推荐的是 3.6.8和2.7.14 首先我电脑是win7系统 在计算机属性右键点开高级设置点击环境变量 将下载 ...

  10. 『现学现忘』Git基础 — 1、版本控制系统介绍

    在具体了解Git之前,首先需要我们了解一下VCS,即版本控制系统(version control system) 1.什么是版本控制系统 版本控制是一种记录一个或若干个文件内容变化,以便将来查阅特定版 ...