POJ 2449 求第K短路

第一道第K短路的题目 QAQ

拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了

题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是出题人写错了)

从这题中还真的学到了很多
1.第k短路的算法 A* 还有用边表实现dij

(注:以下部份资料来源于网上)
所谓A*就是启发是搜索 说白了就是给搜索一个顺序使得搜索更加合理减少无谓的搜索. 如何来确定搜索的顺序?..也就是用一个值来表示 这个值为f[n]..每次搜索取f[x]最小的拓展 那么这个f[n]=h[n]+g[n]
其中f(n) 是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。如果说详细 点,g(n)代表了搜索的广度的优先趋势。但是当h(n) >> g(n)时,可以省略g(n),而提高效率。

A*算法的估价函数可表示为:   
  f’(n) = g’(n) + h’(n)   
这里,f’(n)是估价函数,g’(n)是起点到终点的最短路径值,h’(n)是n到目标的最短路经的启发值。由 于这个f’(n)其实是无法预先知道的,所以我们用前面的估价函数f(n)做近似。g(n)代替g’(n),但 g(n)>=g’(n) 才可(大多数情况下都是满足的,可以不用考虑),h(n)代替h’(n),但h(n)<=h’(n)才可(这一点特别的重 要)。可以证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。我们说应用这种估价函数的 最好优先算法就是

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <iostream>
  6 #include <stack>
  7 #include <queue>
  8 #include <algorithm>
  9
 10 #define ll long long
 11 using namespace std;
 12 const int INF = 0x3f3f3f3f;
 13 const int MAXN = 1111;
 14
 15 struct vertex{
 16     int sum, h, pos;
 17     bool operator < (vertex a) const{
 18         return a.sum + a.h < sum + h;
 19     }
 20 };
 21 struct sc{
 22        int u, v, w, next;
 23 }line1[MAXN*MAXN],line2[MAXN*MAXN];
 24
 25 int link1[MAXN],link2[MAXN],h[MAXN],times[1001];
 26 int n, m, s, e, k;
 27 bool vis[MAXN];
 28 priority_queue <vertex> que;
 29
 30 void init(){
 31     memset(link1, 0, sizeof(link1));
 32     memset(link2, 0, sizeof(link2));
 33     memset(vis,0,sizeof(vis));
 34     memset(h,0x3f,sizeof(h));//h函数初始值为最大
 35     while (!que.empty()) que.pop();
 36     memset(times,0,sizeof(times));
 37 }
 38
 39 void djikstra(){
 40     int i,k,p;
 41     h[e] = 0;
 42     for (p = 1; p <= n; ++p){
 43         k = 0;
 44         for (i = 1; i <= n; ++i)
 45             if (!vis[i] && (!k||h[i]<h[k])) k = i;
 46         vis[k] = true;
 47         k = link2[k];
 48         while (k){
 49             if (h[line2[k].v] > h[line2[k].u] + line2[k].w)
 50                 h[line2[k].v] = h[line2[k].u] + line2[k].w;
 51             k = line2[k].next;
 52         }
 53     }
 54 }
 55
 56 int Astar(){
 57     int t;
 58     vertex g,temp;
 59     g.pos = s;
 60     g.sum = 0;
 61     g.h = h[s];
 62     que.push(g);
 63
 64     if (s==e) ++k;
 65     while (!que.empty()){
 66         g = que.top();//每次取估价函数值最小的节点
 67         que.pop();
 68         ++times[g.pos];
 69         if (times[g.pos] == k && g.pos == e) return g.sum + g.h;
 70         if (times[g.pos] > k) continue;
 71
 72         t = link1[g.pos];
 73         while (t){//扩展,并把其加入优先队列即openlist
 74             temp.sum = g.sum + line1[t].w;
 75             temp.h = h[line1[t].v];
 76             temp.pos = line1[t].v;
 77             que.push(temp);
 78             t = line1[t].next;
 79         }
 80     }
 81     return -1;
 82 }
 83
 84 int main(){
 85     int i, j;
 86     while(cin >> n >> m){
 87         init();
 88         for (i = 1; i <= m; ++i){
 89             cin >> line1[i].u >> line1[i].v >> line1[i].w;
 90             line1[i].next = link1[line1[i].u];//记录与节点u有直接边的节点
 91             link1[line1[i].u] = i;
 92
 93             line2[i].u = line1[i].v;
 94             line2[i].v = line1[i].u;
 95             line2[i].w = line1[i].w;
 96             line2[i].next = link2[line2[i].u];
 97             link2[line2[i].u] = i;
 98         }
 99         cin >> s >> e >> k;
100         djikstra();
101         cout << Astar() << endl;
102     }
103     return 0;
104 }

POJ 2449 求第K短路

时间: 2024-10-13 10:56:40

POJ 2449 求第K短路的相关文章

POJ 2449 Remmarguts&#39; Date(k短路模板)

link:https://vjudge.net/problem/POJ-2449 前面输入与大多最短路题相同 最后一行输入s,t,k 求从s到t的第K短路 #include <iostream> #include <cstring> #include <queue> using namespace std; const int MAXN=1010; struct node { int p,g,h; bool operator < (node a) const {

poj 2449 Remmarguts&#39; Date k短路

/*poj 2449 k短路 A* 估价函数是 s到i的距离+i到t的距离 */ #include<cstdio> #include<queue> #include<vector> #define inf 1e7 #define maxn 100010 using namespace std; int n,m,S,T,K,num1,num2,head1[maxn],head2[maxn],dis[maxn]; int q[maxn],hea,tai,f[maxn],cn

poj 2449 Remmarguts&#39; Date A*+spfa求第k短路

题意: 经典的第k短路,A*算法的经典应用之一. 分析: A*,已走的路程g+到终点的最短距离为启发函数,搜索过程中不判重,第k次到t节点时就求出了第k短路. 代码: //poj 2449 //sep9 #include <iostream> #include <queue> using namespace std; const int maxN=1024; const int maxM=100024; int n,m,s,t,k,e,ne; int head[maxN],nhea

poj 2449 Remmarguts&#39; Date 求第k短路 Astar算法

=.=好菜 #include <iostream> #include <cstdio> #include <string.h> #include <cstring> #include <queue> using namespace std; const int N = 1e3+10; const int M = 100000+10; typedef long long ll; const ll INF = 1e15; int n,m,head[N

POJ 2449Remmarguts&#39; Date 第K短路

Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 29625   Accepted: 8034 Description "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, h

A*算法的认识与求第K短路模板

现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎么求呢? 对于第k短路,可以想到的一个比较朴素的算法就是广度优先搜索,使用优先队列从源点s进行广搜,当第k次搜索到终点t时,所的长度即所求但是这种方法在运行过程中会产生特别多的状态,当图比较简单.k比较小时,可以一试,但是当k较大或者图中点数较多时,会面临爆栈的危险.目前使用比较多的算法是单源最短路

POJ 2499 A*求第K短路

DES就是给你一个图.然后给你起点和终点.问你从起点到终点的第K短路. 第一次接触A*算法. // 大概懂思路了.A*算法需要的估价函数里的两个函数.一个是起点到当前点的消耗. //一个是当前点到目标点的估测消耗.所以需要用Dijstra或者Spfa求出目标点到所有点的最短路. //然后就可以用A*算法来求了. // 确实.学了位运算.链式表. #include<cstdio> #include<iostream> #include<queue> #include<

aStar算法求第k短路

A*的概念主意在于估计函数,f(n)=g(n)+h(n),f(n)是估计函数,g(n)是n节点的当前代价,h(n)是n节点的估计代价:而实际中,存在最优的估计函数f'(n)=g'(n)+h'(n),那么显然我们在A*的估计中,h(n)<=h'(n),否则你将搜不到最优解:(g(n)>=g'(n)我还不怎么清楚为什么啊,大多数情况是g(n)=g'(n),这个可以不用管吧..) 求s->t的第k短路, dist[x]为x->t的最短路 (这个只要反向建边,然后一次spfa,求出任意点到

&lt;学习笔记&gt; A*算法求第k短路

一条前往题面的隧道 简洁题面 第一行给出N(点数),M(边数)(1 <= N <= 1000, 0 <= M <= 100000).. 下面的M行每行给出三个数Ai,Bi,Ti,表示从A到B有一条权值为T的单向边. 最后给出S,T,K,表示求S到T的第K短路. special: 起点与终点相同时,S–>S (d=0) 不能算作一条路. 题目会给出多组数据. 即使有好几条路到T的距离都相同,它们仍被记为不同的路. 正解 A*算法 记g[i]为起点s到i的距离,h[i] (期望值