博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ--2449--Remmarguts' Date【dijkstra_heap+A*】第K短路
阅读量:5763 次
发布时间:2019-06-18

本文共 3067 字,大约阅读时间需要 10 分钟。

链接:

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

第K短路裸题,A*算法没接触过,參考了这篇博客:

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

对于第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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
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
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

转载地址:http://hogkx.baihongyu.com/

你可能感兴趣的文章
项目汇报XMind 6来帮您
查看>>
OSChina 周三乱弹 ——我把你们当学生,而你们却想上我
查看>>
OSChina 周三乱弹 ——趁着我们还有机会,找个对的人去说我爱你
查看>>
OSChina 周一乱弹 —— 今天三餐吃什么呢
查看>>
jodd mvc框架 madvoc 教程(7):注入
查看>>
直播推流sdk & 点播sdk 小记
查看>>
Hibernate4.x之映射关系--一对一映射
查看>>
json作为配置,加注释
查看>>
GNOME3创建连接OracleFS管理软件启动快捷方式
查看>>
HADOOP WINDOWS 开发环境搭建
查看>>
多重继承下的“四不像”
查看>>
spring mvc异常处理设置
查看>>
EBS 11i ojspCompile.pl 编译jsp乱码 encoding
查看>>
前嗅ForeSpider教程:采集新浪新闻
查看>>
前嗅ForeSpider教程:如何创建新任务
查看>>
python基本数据类型
查看>>
Android Development
查看>>
2014年DDoS***事件分析
查看>>
很多时候想问题是如果条件满足了,我将咋么去做,如果条件不满足呢?
查看>>
Redis 集群方案介绍
查看>>