第K短路+严格第K短路
所谓K短路,就是从s到t的第K短的路,第1短就是最短路。
如何求第K短呢?有一种简单的方法是广度优先搜索,记录t出队列的次数,当t第k次出队列时,就是第k短路了。但点数过大时,入队列的节点过多,时间和空间复杂度都较高。
A*是在搜索中常用的优化,一种启发式搜索。简单的说,它可以用公式表示为f(n) = g(n) + f(n),其中,f(n)是从s经由节点n到t的估价函数,g(n)是在状态空间中从s到n的实际代价,h(n)是从n到t的最佳路径估计代价。在设计中,要保证h(n)<= n到t的实际代价,这一点很重要,h(n)越接近真实值,速度越快。
由于启发函数的作用,使得计算机在进行状态转移时尽量避开不可能产生最优解的分支,而选择相对较接近最优解的路径进行搜索,降低了时间和空间复杂度。
算法过程:
1. 将图反向,用dijstra+heap求出t到所有点的最短距离,目的是求所有点到点t的最短路,用dis[i]表示i到t的最短路,其实这就是A*的启发函数,显然:h(n)<= n到t的实际代价。
2. 定义估价函数。我们定义g(n)为从s到n所花费的代价,h(n)为dis[n],显然这符合A*算法的要求。
3. 初始化状态。状态中存放当前到达的点i,fi,gi。显然,fi=gi+dis[i]。初始状态为(S,dis[S],0),存入优先级队列中。
4. 状态转移。假设当前状态所在的点v相邻的点u,我们可以得到转换:(V,fv,gv)-->(U,fu+w[v][u],gv+w[v][u])。
5. 终止条件。每个节点最多入队列K次,当t出队列K次时,即找到解。
例:POJ2449
题意:裸的K短路。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX = 1005;
int n,m;
int start,end,k;
struct Edge
{
int w;
int to;
int next;
};
Edge e[100005];
int head[MAX],edgeNum;
int dis[MAX]; //dis[i]表示从i点到end的最短距离
bool vis[MAX];
int cnt[MAX];
vector<Edge> opp_Graph[MAX];
struct Node
{
int f,g; //f = g+dis[v]
int v; //当前到达的节点
Node(int a, int b,int c):f(a),g(b),v(c){}
bool operator < (const Node& a) const
{
return a.f < f;
}
};
void addEdge(int from, int to, int w)
{
e[edgeNum].to = to;
e[edgeNum].w = w;
e[edgeNum].next = head[from];
head[from] = edgeNum++;
}
void dijikastra(int start)
{
int i;
memset(vis,0,sizeof(vis));
for(i = 1; i <= n; i++)
dis[i] = INF;
dis[start] = 0;
priority_queue<Node> que;
que.push(Node(0,0,start));
Node next(0,0,0);
while(!que.empty())
{
Node now = que.top();
que.pop();
if(vis[now.v]) //从集合T中选取具有最短距离的节点
continue;
vis[now.v] = true; //标记节点已从集合T加入到集合S中
for(i = 0; i < opp_Graph[now.v].size(); i++) //更新从源点到其它节点(集合T中)的最短距离
{
Edge edge = opp_Graph[now.v][i];
if(!vis[edge.to] && dis[now.v] + edge.w < dis[edge.to]) //加不加前面的判断无所谓
{
dis[edge.to] = dis[now.v] + edge.w;
next.f = dis[edge.to];
next.v = edge.to;
que.push(next);
}
}
}
}
int A_Star()
{
int i;
priority_queue<Node> que;
if(dis[start] == INF)
return -1;
que.push(Node(dis[start],0,start));
Node next(0,0,0);
while(!que.empty())
{
Node now = que.top();
que.pop();
cnt[now.v]++;
if(cnt[end] == k) return now.f;
//严格最短路的判断条件为 cnt[end] == k&&now.f>min(zuiduanlu)
if(cnt[now.v] > k)
continue;
for(i = head[now.v]; i != -1; i = e[i].next)
{
next.v = e[i].to;
next.g = now.g + e[i].w;
next.f = next.g + dis[e[i].to];
que.push(next);
}
}
return -1;
}
int main()
{
int i;
int from,to,w;
edgeNum = 0;
memset(head,-1,sizeof(head));
memset(opp_Graph,0,sizeof(opp_Graph));
memset(cnt,0,sizeof(cnt));
scanf("%d %d",&n,&m);
Edge edge;
for(i = 1; i <= m; i++)
{
scanf("%d %d %d",&from,&to,&w);
addEdge(from,to,w);
edge.to = from;
edge.w = w;
opp_Graph[to].push_back(edge);
}
scanf("%d %d %d",&start,&end,&k);
if(start == end)
k++;
dijikastra(end);
int result = A_Star();
printf("%d\n",result);
return 0;
}
第K短路+严格第K短路的更多相关文章
- HDU 4396More lumber is required 过至少K条边的最短路
/* ** 题目要求过最少k条边的最短路 */ #include <iostream> #include <cstdio> #include <cstring> # ...
- BZOJ2125 最短路 【仙人掌最短路】
题目 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. 输入格式 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一 ...
- [CareerCup] 13.1 Print Last K Lines 打印最后K行
13.1 Write a method to print the last K lines of an input file using C++. 这道题让我们用C++来打印一个输入文本的最后K行,最 ...
- 一些简单的问题. 2的10次方与k (涉及到b k m的要用乘来解读)
2的10次方是k k就表示2的10次方 2的16次方,解读为 2的6次方(64)*2的10次方(k) 简写为64k 64k=64*k 同理2的20次方 解读为2的10次方*2的10次方 k ...
- 机器学习 —— 基础整理(三)生成式模型的非参数方法: Parzen窗估计、k近邻估计;k近邻分类器
本文简述了以下内容: (一)生成式模型的非参数方法 (二)Parzen窗估计 (三)k近邻估计 (四)k近邻分类器(k-nearest neighbor,kNN) (一)非参数方法(Non-param ...
- 快速排序/快速查找(第k个, 前k个问题)
//快速排序:Partition分割函数,三数中值分割 bool g_bInvalidInput = false; int median3(int* data, int start, int end) ...
- 在数组a中,a[i]+a[j]=a[k],求a[k]的最大值,a[k]max——猎八哥fly
在数组a中,a[i]+a[j]=a[k],求a[k]的最大值,a[k]max. 思路:将a中的数组两两相加,组成一个新的数组.并将新的数组和a数组进行sort排序.然后将a数组从大到小与新数组比较,如 ...
- [LeetCode] Top K Frequent Words 前K个高频词
Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...
- [LeetCode] K Inverse Pairs Array K个翻转对数组
Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that ...
随机推荐
- fastfdfs搭配nginx
fastfdfs搭配nginx 下载fastdfs-nginx-module 模块 wget https://github.com/happyfish100/fastdfs-nginx-module/ ...
- Java第二十五天,多线程之等待唤醒机制
当线程被创建并且被启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,而是具有以下多种状态: 这六种状态之间的转换关系如下: 1.等待唤醒机制 注意: (1)两个线程之间必须用同步代码块 ...
- SpringBoot 2.x 开发案例之前后端分离鉴权
前言 阅读本文需要一定的前后端开发基础,前后端分离已成为互联网项目开发的业界标准使用方式,通过Nginx代理+Tomcat的方式有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微 ...
- k8s~helm镜像版本永远不要用latest
对于容器编排工具k8s来说,你可以使用它规定的yaml格式的脚本,使用客户端kubectl来与k8s进行通讯,将你定义好的yaml部署脚本应用到k8s集群上,而这对yaml脚本一般来说都是很像的,就是 ...
- 微服务框架-Spring Cloud
Spring Cloud入门 微服务与微服务架构 微服务架构是一种新型的系统架构.其设计思路是,将单体架构系统拆分为多个可以相互调用.配合的独立运行的小程序.这每个小程序对整体系统所提供的功能就称为微 ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十三)之Strings
Immutable Strings Objects of the String class are immutable. If you examine the JDK documentation fo ...
- python基础入门:matplotlib绘制多Y轴画图(附源码)
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:屁屁酱 PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...
- Linux下安装Redis4.0版本(简便方法)
Redis介绍: Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久 ...
- C - Roads in the North DFS+树的直径
Building and maintaining roads among communities in the far North is an expensive business. With thi ...
- 资料整理:python接口类
1开发原则(七大原则) 一:开放封闭原则 二:接口隔离原则(将不同接口对象一一展现出来,分别调用各自的接口,完成各自的功能) 三:依赖倒置原则 高级模块不能依赖低级模块,可以依赖抽象 规范的定义: 高 ...