POJ 2449 A*+SPFA
A*算法求第k短路流程:
1)计算h[],即当前点到t的估计值
若为有向图,建立反向图求出h[]。若为无向图,可直接求解h[]。可通过SPFA求解。
2)A*搜索
每次找到新节点就直接加入队列,计算出估价函数f[]=g[]+h[],然后加入优先队列中。(此步不可优化,否则可能造成失解)
常用STL priority_queue实现,要注意默认是大根堆,可重载<实现小根堆。
3)若根入队k次,返回
ADD:
该题几个注意事项及优化:
a)若起始点h值==INF,不搜。
b)若一个点入队超过k次,不搜。
c)邻接表代替邻接矩阵,防止重边。
d)该题中若s==t,距离为0的路径不能计入。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 0x3f3f3f3f
#define N 1005
#define M 100005 using namespace std; struct Edge
{
int y,w,ne;
}e[M*],re[M*]; int x,y,w,n,m,s,t,k;
int be[N],all;
int rbe[N],rall;
int h[N],cnt[N];
bool vis[N]; struct Point
{
int x,g;
bool operator < (const Point T) const
{
return g+h[x]>T.g+h[T.x];
}
}; void add(int x, int y, int w)
{
e[all].y=y;
e[all].w=w;
e[all].ne=be[x];
be[x]=all++;
}
void radd(int x, int y, int w)
{
re[rall].y=y;
re[rall].w=w;
re[rall].ne=rbe[x];
rbe[x]=rall++;
} void SPFA(int s)
{
queue< int > q;
while(!q.empty())
q.pop();
for(int i=; i<=n; i++)
{
h[i]=INF;
vis[i]=;
}
h[s]=;
vis[s]=;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=;
for(int i=rbe[u]; i!=-; i=re[i].ne)
{
int v=re[i].y;
if(h[v]>h[u]+re[i].w)
{
h[v]=h[u]+re[i].w;
if(!vis[v])
{
vis[v]=;
q.push(v);
}
}
}
}
} int Astar(int s, int t, int k)
{
SPFA(t);
if(h[s]==INF) return -;
priority_queue< Point > q;
while(!q.empty())
q.pop();
memset(vis,,sizeof(vis));
memset(cnt,,sizeof(cnt));
Point cur,nxt;
cur.x=s;
cur.g=;
q.push(cur);
while(!q.empty())
{
cur=q.top();
q.pop();
if((++cnt[cur.x])>k) continue;
if(cnt[t]==k)
return cur.g;
for(int i=be[cur.x]; i!=-; i=e[i].ne)
{
nxt.x=e[i].y;
nxt.g=cur.g+e[i].w;
q.push(nxt);
}
}
return -;
} void init()
{
all=;
memset(be,-,sizeof(be));
rall=;
memset(rbe,-,sizeof(rbe));
} int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=; i<m; i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
radd(y,x,w);
}
scanf("%d%d%d",&s,&t,&k);
if(s==t) k++;
printf("%d\n",Astar(s,t,k));
return ;
} /* 2 4
1 2 1
1 2 2
1 2 3
2 1 5
1 2 5 */
POJ 2449 A*+SPFA的更多相关文章
- poj 2449 Remmarguts' Date 【SPFA+Astar】【古典】
称号:poj 2449 Remmarguts' Date 意甲冠军:给定一个图,乞讨k短路. 算法:SPFA求最短路 + AStar 以下引用大牛的分析: 首先,为了说话方便,列出一些术语: 在启示式 ...
- POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang
题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...
- POJ 2449:Remmarguts' Date(A* + SPFA)
题目链接 题意 给出n个点m条有向边,源点s,汇点t,k.问s到t的第k短路的路径长度是多少,不存在输出-1. 思路 A*算法是启发式搜索,通过一个估价函数 f(p) = g(p) + h(p) ,其 ...
- poj 2449 Remmarguts' Date K短路+A*
题目链接:http://poj.org/problem?id=2449 "Good man never makes girls wait or breaks an appointment!& ...
- poj 2449(A*求第K短路)
题目链接:http://poj.org/problem?id=2449 思路:我们可以定义g[x]为源点到当前点的距离,h[x]为当前点到目标节点的最短距离,显然有h[x]<=h*[x](h*[ ...
- poj 2449 k短路+A*算法
http://poj.org/problem?id=2449 K短路的定义: 1.如果起点终点相同,那么0并不是最短路,而是要出去一圈回来之后才是最短路,那么第K短路也是一样. 2.每个顶点和每条边都 ...
- poj 2449 Remmarguts' Date(K短路,A*算法)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013081425/article/details/26729375 http://poj.org/ ...
- poj 2449 Remmarguts' Date (k短路模板)
Remmarguts' Date http://poj.org/problem?id=2449 Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- POJ 1860(spfa)
http://poj.org/problem?id=1860 题意:汇率转换,与之前的2240有点类似,不同的是那个题它去换钱的时候,是不需要手续费的,这个题是需要手续费的,这是个很大的不同. 思路: ...
随机推荐
- C++中用辗转相除法求两个数的最大公约数和最小公倍数
两个数的最大公约数:不能大于两个数中的最小值,算法口诀:小的给大的,余数给小的,整除返回小的,即最大公约数,(res=max%min)==0? max=min,min=res return min; ...
- NSStringDrawingOptions-b
如果options参数为NSStringDrawingUsesLineFragmentOrigin,那么整个文本将以每行组成的矩形为单位计算整个文本的尺寸.(在这里有点奇怪,因为字体高度大概是13.8 ...
- Netsharp快速入门(之12) 销售管理(开发发货单工作区)
作者:秋时 杨昶 时间:2014-02-15 转载须说明出处 4.4 发货单 4.4.1 部件工作区设置 1.设置部件工作区,需要设置的部件如下 2.设置单据和明细列表的字段,设置完成 ...
- uva 10859
刘书例题 树形dp #include <cstdio> #include <cstdlib> #include <cmath> #include <map& ...
- 【面试题030】最小的k个数
[面试题030]最小的k个数 题目: 输入n个整数,找出其中最小的k个数. 例如输入4.5.1.6.2.7.3.8这8个字,则其中最小的4个数字是1.2.3.4. 思路一: ...
- hdoj 2204 Eddy's爱好
原文链接:http://www.cnblogs.com/DrunBee/archive/2012/09/05/2672546.html 题意:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K ...
- POJ 3277 City Horizon(叶子节点为[a,a+1)的线段树+离散化)
网上还有用unique函数和lowerbound函数离散的方法,可以百度搜下题解就有. 这里给出介绍unique函数的链接:http://www.cnblogs.com/zhangshu/archiv ...
- POJ 3070 Fibonacci(矩阵快速幂)
题目链接 题意 : 用矩阵相乘求斐波那契数的后四位. 思路 :基本上纯矩阵快速幂. #include <iostream> #include <cstring> #includ ...
- Android 手机震动 设置震动时间
开启震动,单次,5秒: Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); //震动5秒 vibrator.vibra ...
- NuGet学习笔记——初识NuGet及快速安装使用
源自:http://kb.cnblogs.com/page/143190/