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,求出任意点到t点的距离即可
那么点x的g(x)=到达当前点的花费
h(x) = dist[x] , 可以知道h(x)=h'(x),所以可以保证搜到最优解。
每次出出队列的都是当前f(x)最小的点,
所以如果点x出队列, 那么就cnt[x]++,
当cnt[x]==k时,那么当前的f(x)就是第k短路,因为第一次出队列时,肯定是最短路上的点,第二次是次短路上的点,第k次,自然就是第k短路上的点了。
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
#include <iostream>
typedef __int64 LL;
const int INF = << ; /*
*/
const int N = + ;
struct Node
{
int from, to, dis, next;
}g[N*];
int head[N], e;
int dist[N];
bool vis[N];
int cnt[N];
void addEdge(int u, int v, int dis)
{
g[e].from = u;
g[e].to = v;
g[e].dis = dis;
g[e].next = head[u];
head[u] = e++;
} void spfa(int src, int n)
{
for (int i = ;i <= n;++i)
dist[i] = INF;
std::queue<int> q;
q.push(src);
dist[src] = ;
while (!q.empty())
{
int u = q.front(); q.pop();
vis[u] = false;
for (int i = head[u];i + ;i = g[i].next)
{
int v = g[i].to;
if (dist[v] > dist[u] + g[i].dis)
{
dist[v] = dist[u] + g[i].dis;
if (!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
}
void init()
{
e = ;
memset(head, -, sizeof(head));
}
void reverse()
{
memset(head, -, sizeof(head));
int te = e;
e = ;
for (int i = ;i < te;++i)
addEdge(g[i].to, g[i].from, g[i].dis);
}
struct Node2
{
int to;
int g;
bool operator<(const Node2&rhs)const
{
return g + dist[to] > rhs.g + dist[rhs.to];
}
};
/*
因为每次出队列的都是最短的, 所以该点是第几次出队列,就表示是该点到终点的第k短路
*/
int aStar(int src, int des, int k)
{
std::priority_queue<Node2> q;
Node2 cur, tmp;
cur.to = src;
cur.g = ;
q.push(cur);
while (!q.empty())
{
cur = q.top(); q.pop();
int u = cur.to;
cnt[u]++;
if (cnt[u] > k) continue;
if (cnt[u] == k)
return cur.g + dist[u];
for (int i = head[u];i + ;i = g[i].next)
{
int v = g[i].to;
tmp.to = v;
tmp.g = cur.g + g[i].dis;
q.push(tmp);
}
}
return -;
}
int main()
{
int n, m, src, des, k;
while (scanf("%d%d", &n, &m) != EOF)
{
init();
int u, v, dis;
for (int i = ;i <= m;++i)
{
scanf("%d%d%d", &u, &v, &dis);
addEdge(v, u, dis);
}
scanf("%d%d%d", &src, &des, &k);
spfa(des, n);
reverse();
if (src == des)k++;//如果起点等于终点,那么最短路其实是什么都不走
int ans = aStar(src, des, k);
printf("%d\n", ans);
}
return ;
}
aStar算法求第k短路的更多相关文章
- A* 算法求第 K 短路
一种具有 \(f(n)=g(n)+h(n)\) 策略的启发式算法能成为 A* 算法的充分条件是: 搜索树上存在着从起始点到终了点的最优路径. 问题域是有限的. 所有结点的子结点的搜索代价值 \(> ...
- A*算法的认识与求第K短路模板
现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎 ...
- poj 2449(A*求第K短路)
题目链接:http://poj.org/problem?id=2449 思路:我们可以定义g[x]为源点到当前点的距离,h[x]为当前点到目标节点的最短距离,显然有h[x]<=h*[x](h*[ ...
- POJ 2449 求第K短路
第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是 ...
- POJ 2499 A*求第K短路
DES就是给你一个图.然后给你起点和终点.问你从起点到终点的第K短路. 第一次接触A*算法. 题目链接:Remmarguts' Date 转载:http://blog.csdn.net/mbxc816 ...
- A* 算法求第k短路径
A*算法是一类贪心算法,其可以用于寻找最优路径.我们可以利用A*算法来求第k短路径. 一条路径可以由两部分组成,第一部分是一个从出发到达任意点的任意路径,而第二部分是从第一部分的末端出发,到终点的最短 ...
- poj 2449 Remmarguts' Date 求第k短路 Astar算法
=.=好菜 #include <iostream> #include <cstdio> #include <string.h> #include <cstri ...
- ACM模板~求第k短路 ~~~A*+Dijkstra
#include <map> #include <set> #include <cmath> #include <ctime> #include < ...
- POJ 2449 Remmarguts' Date (K短路 A*算法)
题目链接 Description "Good man never makes girls wait or breaks an appointment!" said the mand ...
随机推荐
- Spring2.5学习3.3_@Autowire注解实现手动装配
@Autowired默认按类型装配,假设我在personDao 字段上加了@Autowired注解,那么就会默认取personDao 字段的类型在Spring容器中寻找与这个类型匹配的bean,寻找到 ...
- Ubuntu 安装和配置minicom
Ubuntu 安装和配置minicom 1 . 安装 Minicom 用新立得软件管理器下载minicom 2.配置Minicom shell下输入 minicom -s 打开配置界面 进入Seria ...
- Swift - 标签条(UITabBar)标签页控制器(UITabBarController)用法
App底部的tab标签页可以方便的把功能模块划分清楚,只需点击相应的标签页就可以展示完全独立的视图页面,同时各标签页间的视图也可以进行数据交换. TabBarItem系统自带图标样式(System ...
- sqlserver 自学笔记 函数实训 学分学期转换函数的设计
设计目的: 1.运用sql基本知识,编写学期转换函数. 2.运用sql基本知识,编写学分转换函数,将考试成绩转换为学分 3.通过上述函数的编写与调试,熟练掌握 sql函数的编写.调试与使用方法. 设计 ...
- wikioi 1014 装箱问题
来源:http://wikioi.com/problem/1014/ 1014 装箱问题 29人推荐 收藏 发题解 提交代码 报错 题目描写叙述 输入描写叙述 输出描写叙述 例子输入 例子输出 提示 ...
- 使用Android简单实现有道电子词典
前言: 毕业设计的内容,仅仅有Java基础.没学过Android. 本着用到什么学什么.花费了10多个晚上完毕毕业设计. 当然,仅仅是简单的实线了电子词典功能,自始至终没有考虑过性能等问题. 本电子词 ...
- [Cocos2d-x]解决Android平台ndk-build时不自动删除外部库
参考链接: http://blog.chinaunix.net/uid-26009923-id-3430612.html http://hi.baidu.com/hpyfei/item/52a2b21 ...
- PHP中如何实现 “在页面中一边执行一边输出” 的效果
<?php set_time_limit(0); //在有关数据库的大量数据的时候,可以将其设置为0,表示无限制. ob_end_clean(); //在循环输出前,要关闭 ...
- VS快捷键教程
删除或剪切一行(Ctrl + X) 不须要选择不论什么文本, 用来剪切一行, 最经常使用来删除一行. 删除一行也能用 Shift+Delete 格式化整个文档(Ctrl + K, Ctrl + D) ...
- hdu3829(最大独立集)
传送门:Cat VS Dog 题意:动物园有N只猫,M只狗,P个小孩.每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫, 如果他讨厌狗,那么他就喜欢猫.某个小孩能开心,当且仅当他喜欢 ...