链接:http://poj.org/problem?id=2449

题意:告诉你有n个顶点,m条边,并把这些边的信息告诉你:起点、终点、权值。再告诉你s、t、k。需求出s到t的第k短路,没有则输出-1。

第K短路裸题,A*算法没接触过,參考了这篇博客:http://www.cnblogs.com/n-u-l-l/archive/2012/07/29/2614194.html

下面大体字摘自这篇博文,讲的非常清楚:

对于第k短路,能够想到的一个比較朴素的算法就是广度优先搜索,使用优先队列从源点s进行广搜。当第k次搜索到终点t时,所得长度即所求可是这样的方法在执行过程中会产生特别多的状态。当图比較简单、k比較小时,能够一试。可是当k较大或者图中点数较多时。会面临爆栈的危急。

眼下使用比較多的算法是单源最短路配合A*。A*是搜索中比較高级的方式,A*算法结合了启示式方法(这样的方法通过充分利用图给出的信息来动态的作出决定而使搜索次数大大减少)和形式化方法(这样的方法不利用图给出的信息,而仅通过数学的形式分析,如Dijkstra算法)。

它通过一个估价函数f(h)来预计图中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时。它会尝试其它路径。对于A*。估价函数=当前值+当前位置到终点的距离,即f(p)=g(p)+h(p),每次扩展估价函数值最小的一个。对于第k短路算法来说,g(p)为从源点s到当前点p所走的路径长度,h(p)为从当前点p到终点t的最短路。因此f(p)的意义就是从s依照当前路径经过p点后到达t的总距离。也就是每次扩展都是有方向的。这样不管对提高出解的速度还是减少扩展的状态数目都是有优点的。

为了加快计算。h(p)须要在搜索之前进行预处理,仅仅要将原图的全部边反向。再从终点t做一次单源最短路就可以得到h(p)。单源最短路求法有Dijkstra,Bellman-Ford,SPFA等。

  详细步骤:

  这里我们使用链式前向星来存储如图。因为须要预处理全部点到终点的最短路,就须要将图G中全部边反向得到图G',再从终点t做一次单源最短路,所以实际上就是两张图。

  (1)将有向图的全部边反向(无向图能够省略此步),以原图终点t为源点做一次单源最短路,结果记入数组dis[i]中,dis[i]即为原图中点i到点t的最短距离。

这里的dis[i]即上述的h(p);

  (2)新建一个优先队列。将源点s增加到队列中。

  (3)从优先队列中弹出f(p)最小的点p(这里假设存在f(p)相等的点,则弹出g(p)最小的点),假设点p就是终点t,则计算t出队列的次数,假设当前为t的第k次出队。则当前路径长度就是s到t的第k短路。算法结束。否则遍历与p相连的全部的边,将扩展出的到p的邻接点信息增加到优先队列。

  值得注意的是。当s==t时须要计算(k+1)短路。由于s到t这条距离为0的路不能算在这k短路中,这时仅仅需将k自增1后再求第k短路就可以。

这道题比較坑的地方就是上面说的 s==t时须要计算(k+1)短路。m==0时也即s==t时。k+1短路不存在。应输出-1。还有就是dist[s]!=INF时。尽管A*能找到最短路,但假设k较大。不一定存在第k短路。所以应当有个标记。我忘记加标记多WA了一发

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1struct NODE{int u;int f,g;bool operator < (const NODE &t) const{if(t.f==f)  return t.g > g;return t.f < f;}
};
struct EDGE{int u,w,next;
};
struct NODE2{int u,dis;bool operator < (const NODE2 &t) const{return t.dis < dis;}
};
EDGE edge[MAXN],redge[MAXN];
int head[1010],rhead[1010],vis[1010],dist[1010];
int n,m,cnt,rcnt,ans,flag;
void add_edge(int a,int b,int c){edge[cnt].u = b;edge[cnt].w = c;edge[cnt].next = head[a];head[a] = cnt++;redge[rcnt].u = a;redge[rcnt].w = c;redge[rcnt].next = rhead[b];rhead[b] = rcnt++;
}
void dijkstra_heap(int v){NODE2 t1,t2;int i,j;for(i=1;i<=n;i++)   dist[i] = INF;dist[v] = 0;t1.u = v;t1.dis = 0;priority_queue<NODE2>q;q.push(t1);while(!q.empty()){t1 = q.top();q.pop();if(vis[t1.u])   continue;vis[t1.u] = 1;for(i=rhead[t1.u];i!=-1;i=redge[i].next){int x = redge[i].w;if(dist[t1.u]+x<dist[redge[i].u]){dist[redge[i].u] = x + dist[t1.u];t2.dis = dist[redge[i].u];t2.u = redge[i].u;q.push(t2);}}}
}
void Astar(int s,int t,int k){int i,j=0;NODE t1,t2;priority_queue<NODE>q;t1.u = s;t1.g = 0;t1.f = t1.g + dist[s];q.push(t1);while(!q.empty()){t1 = q.top();q.pop();if(t1.u==t) j++;if(j==k){ans = t1.f;flag = 1;       //没加标记。WA出翔return ;}for(i=head[t1.u];i!=-1;i=edge[i].next){t2.u = edge[i].u;t2.g = t1.g + edge[i].w;t2.f = t2.g + dist[t2.u];q.push(t2);}}
}
int main(){int i,j;int s,t,k;int a,b,c;while(scanf("%d%d",&n,&m)!=EOF){memset(head,-1,sizeof(head));memset(rhead,-1,sizeof(rhead));memset(vis,0,sizeof(vis));cnt = rcnt = 0;ans = 0;flag = 0;for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);add_edge(a,b,c);}scanf("%d%d%d",&s,&t,&k);if(s==t)    k++;dijkstra_heap(t);if(dist[s]==INF&&m==0){puts("-1");continue;}Astar(s,t,k);if(!flag)    puts("-1");else    printf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/claireyuancy/p/6906746.html

POJ--2449--Remmarguts#39; Date【dijkstra_heap+A*】第K短路相关推荐

  1. POJ 2449 Remmarguts' Date [第k短路]

    Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu Descripti ...

  2. poj 2449 Remmarguts' Date 启发式搜索 A*算法

    做这个题算是学了学spfa算法,一开始感觉spfa和dij好像:dij找最小点松弛,spfa就是一个一个的松弛,松到不能松. 求S到T的第K短路 思路:这个算法的思路是从源点S优雅的暴力跑bfs,用优 ...

  3. POJ 2449 Remmarguts' Date(第K短路 + A* + 最短路)题解

    题意:找出第k短路,输出长度,没有输出-1 思路:这题可以用A*做.A*的原理是这样,我们用一个函数:f = g + h 来表示当前点的预期步数,f代表当前点的预期步数,g代表从起点走到当前的步数,h ...

  4. POJ 2449 Remmarguts' Date(k短路模板)

    link:https://vjudge.net/problem/POJ-2449 前面输入与大多最短路题相同 最后一行输入s,t,k 求从s到t的第K短路 wiki link: https://en. ...

  5. POJ - 2449 Remmarguts' Date(第k短路:spfa+A*)

    题目链接:点击查看 题目大意:给出一个有向图,求第k短路 题目分析:偷学了一波A*,本来以为是多难的算法,其实就是bfs+优先队列的升级版,之前看的那些博客写的都太深奥了,以至于看了一半啥都没看懂然后 ...

  6. POJ 2449 Remmarguts' Date

    POJ_2449 一开始我的思路就是把图上每个点搞一个容量不小于K的最大堆和最小堆,最小堆用于取当前该节点的第某短路值,最大堆用来保存前K小的最短路. 最后为了每次能查询全局最小值,再把N个点放到一个 ...

  7. Poj2449 Remmarguts' Date 【A*搜索】K短路

    http://poj.org/problem?id=2449 A*搜索求K短路. #include <cstdio> #include <cstring> #include & ...

  8. poj 2449 A*求k短路

    A*的入门题目,需要注意的是当图中只有一个点的时候k短路是不存在的. 1 #include <iostream> 2 #include <cstring> 3 #include ...

  9. poj 1681 Painter#39;s Problem(高斯消元)

    http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. 注意依据自由变元求其它解及求最优值 ...

最新文章

  1. 深度学习 免费课程_深入学习深度学习,提供15项免费在线课程
  2. springboot集成prometheus
  3. 大型网站系统与Java中间件实践pdf
  4. 前后端分离 获取用户ip_前后端分离应用——用户信息传递
  5. 【论文】赛尔原创 | EMNLP 2019基于知识库检索器的实体一致性端到端任务型对话系统...
  6. 2021版:《人人都是产品经理》系列图书的说明
  7. ubuntu 解压与压缩 zip 文件
  8. 布尔表达式可满足性问题(SAT)与库克-列文定理(下)
  9. C# 报表设计器 (winform 设计端)开发与实现生成网页的HTML报表 开放源码及调试
  10. Bootstrap框架——栅格系统
  11. 海淘 亚马逊 冻结账号 怎么办?
  12. mysql的primary key_MySQL Primary Key约束
  13. MySQL数据库有哪些特点
  14. 业务中台-业务架构图
  15. Trinity 概述(一)
  16. 谷歌地图拼接软件_宽77米,高60米,南极小岛出现一个“巨洞”,谷歌地图清晰显示...
  17. 冷门指标移中平均线和多空指数的完美结合(一定要看)
  18. DirectX11-硬件多实例渲染
  19. pcap_findalldevs_ex 各参数简述
  20. 少儿编程 电子学会图形化编程等级考试Scratch三级真题解析(选择题)2021-12

热门文章

  1. 使用canvas绘制小程序码
  2. 删除两个字符串中的特定字符使其相等,统计删除的字符的ASCII和
  3. HttpServletResponse对象介绍
  4. JavaScript 中遍历对象的属性
  5. 关于iOS APP 需要支持ipv6-only 开发者需要做的事情
  6. 7. SQL -- 创建数据库(表,字段)
  7. Linux基金会:Linux已经战胜微软
  8. 共享一PYTHON 相关应用领域的介绍资料
  9. android中到webservice用法
  10. Widget(桌面插件)