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

K短路的定义:

1.如果起点终点相同,那么0并不是最短路,而是要出去一圈回来之后才是最短路,那么第K短路也是一样。

2.每个顶点和每条边都可以使用多次。(可以存在环和来回走)

给定起终点,求K短路的长度

然后求K短路使用A*算法,其估价函数f(n) = g(n)+h(n),h(n)是终点到结点n的最短路径,g(n)是起点到结点n的实际代价, 这样选择显然能满足A*估价函数的要求,g(n)>=g'(n),

h(n)<=h'(n)。

h(n)可以对原图的逆图进行SPFA得出。

终止条件是,如果终点第K次出队的话,那么表明已经找到第K短路。

注意处理起点终点不连通的情况。

#pragma comment(linker, "/STACK:36777216")
#pragma GCC optimize ("O2")
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
#define clr1(x) memset(x,-1,sizeof(x))
#define eps 1e-9
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
const int modo = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int inf = 0x3fffffff;
const int maxn = 1005,maxm = 100005;
struct edge{
int v,w,next;
edge(){};
edge(int vv,int ww,int nnext):v(vv),w(ww),next(nnext){};
}e[maxm<<1];
struct node{
int f,g,v;
node(){};
node(int ff,int gg,int vv):f(ff),g(gg),v(vv){};
bool operator < (const node &a) const{
return a.f < f;
}
};
int head[maxn],tail[maxn],dist[maxn],inq[maxn];
int n,m,s,t,k,ecnt;
void init()
{
clr1(head),clr1(tail);
ecnt = 0;
fill(dist,dist+maxn,inf);
clr0(inq);
}
void add(int u,int v,int w)
{
e[ecnt] = edge(v,w,head[u]);
head[u] = ecnt++;
e[ecnt] = edge(u,w,tail[v]);
tail[v] = ecnt++;
}
void spfa(int src)
{
queue<int> q;
q.push(src);dist[src] = 0,inq[src] = 1;
while(!q.empty()){
int cur = q.front();
q.pop();inq[cur] = 0;
for(int i = tail[cur];i != -1;i = e[i].next){
int nxt = e[i].v;
if(dist[nxt] > dist[cur] + e[i].w){
dist[nxt] = dist[cur] + e[i].w;
if(!inq[nxt])
inq[nxt] = 1,q.push(nxt);
}
}
} }
int Astar(int src,int dst){
priority_queue<node> q;
if(dist[src] == inf)
return -1;
clr0(inq);
q.push(node(dist[src],0,src));
while(!q.empty()){
node cur = q.top();
q.pop();
inq[cur.v]++;
if(inq[dst] == k)
return cur.f;
if(inq[cur.v] > k)
continue;
for(int i = head[cur.v];i != -1;i = e[i].next){
node nxt(dist[e[i].v] + e[i].w + cur.g,e[i].w + cur.g,e[i].v);
q.push(nxt);
}
}
return -1;
}
int main(){
int u,v,w;
while(~RD2(n,m)){
init();
while(m--){
RD3(u,v,w);u--,v--;
add(u,v,w);
}
RD3(s,t,k);s--,t--;
spfa(t);
if(s == t)//如果起点终点相同,0不是第1短路径。。
k++;
printf("%d\n",Astar(s,t));
}
return 0;
}

最新文章

  1. 一种简单的md5加盐加密的方法(防止彩虹表撞库)
  2. Linux网络查看命令
  3. Oracle 11g导出空表、少表的解决办法
  4. Using Recursive Common table expressions to represent Tree structures
  5. Winform开发框架之附件管理应用
  6. &lt;转&gt;Npoi导入导出Excel操作&lt;载&gt;
  7. 《more effective c++》条款26 限制类对象的个数
  8. Oracle 中 for update 和 for update nowait 的区别
  9. 动态加载JS(css)文件
  10. 关于verilog中if与case语句不完整产生锁存器的问题 分类: FPGA 2014-11-08 17:39 260人阅读 评论(0) 收藏
  11. CentOS下安装无线网卡驱动 (转)
  12. ASP.NET页面跳转
  13. sql语句中单引号嵌套问题
  14. lesson - 10 shell 基础知识
  15. Java知多少(86)文本框和文本区的输入输出
  16. 导入testng管理测试用例
  17. 用CBrother将excel中的数据转换为C语言头文件
  18. dos下edit编辑器的快捷命令一览
  19. springBoot整合MyBatise及简单应用
  20. December 28th 2016 Week 53rd Wednesday

热门文章

  1. Liunx history
  2. 前端面试问题js汇总
  3. .net序列化
  4. 厉害了,PS大神真的能改变世界!
  5. MySQL单行注释和多行释
  6. 部署描述符(web.xml)和标注(annotation)
  7. ubuntu安装jre
  8. 第一次java实验报告
  9. java 内存, 类加载g
  10. 通过脚本命令cacls提升某个用户都某路径的操作权限