poj 2449 Remmarguts' Date--k短路--spfa+A*

/*
	k短路问题
	spfa+A*
	A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx
	初识A*算法 http://tekbots.eefocus.com/article/10-01/1688061264487401.html

	A*算法就是通过估价函数(f[x]=g[x]+h[x])优先选择更接近目标的节点进行搜索

	再来说第k次到达t就是到t的k短路:A*其实是一个优化,主要算法还是一个广搜,捡着较近的路走,
	第一次肯定时最短的,然后因为是广搜,不会再最短的,所以第二次到达是第二短的,所以,
	第k次到达就是第k短了

	在本题中  g[x]是s到x的实际距离,
	h[x]是x到t的估计代价,这个可以通过求各点到t的最短路得到
*/
#include<stdio.h>
#include<queue>
using namespace std;
int n,m,k,s,t;
struct edge//存储边
{
	int yong;
	int head[1005];
	int v[100005];
	int next[100005];
	int w[100005];
	void clear()
	{
		yong=1;
		memset(head,0,sizeof(head));
	}
	void add(int a,int b,int c)
	{
		v[yong]=b;
		w[yong]=c;
		next[yong]=head[a];
		head[a]=yong;
		yong++;
	}
}e,e2;//正向边和反向边
int dist[1005],vis[1005],cnt[1005];
struct node//A*的时候用到的优先队列节点
{
	int v,g,h;//节点号  估价函数里边的那两项
	friend bool operator<(node a,node b)
	{
		return a.g+a.h>b.g+b.h;
	}
};
void spfa()//求逆向最短路
{
	int i,j,u,v;
	queue<int>q;
	for(i=0;i<=n;++i)
		dist[i]=0x7fffffff;
	memset(vis,0,sizeof(vis));
	vis[t]=1;
	dist[t]=0;
	q.push(t);
	while(!q.empty())
	{
		u=q.front();
		q.pop();
		vis[u]=0;
		for(j=e2.head[u];j;j=e2.next[j])
		{
			v=e2.v[j];
			if(dist[v]>dist[u]+e2.w[j])
			{
				dist[v]=dist[u]+e2.w[j];
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}
int a_star()//A*
{
	if(s==t) ++k;
	if(dist[s]==0x7fffffff)
		return -1;
	memset(cnt,0,sizeof(cnt));
	priority_queue<node>q;
	node nod,no;
	nod.v=s;
	nod.g=0;
	nod.h=dist[s];
	q.push(nod);
	while(!q.empty())
	{
		nod=q.top();
		q.pop();
		cnt[nod.v]++;
		if(cnt[t]==k) return nod.g;//找到则返回长度
		if(cnt[nod.v]>k) continue;//对任意一个节点来说  只需求它的k短路  
		//若不是目标路径上的节点,那就没什么说的了;若是,也只需要k短,这里的k短就可以造成t产生k短
		for(int i=e.head[nod.v];i;i=e.next[i])
		{
			no.v=e.v[i];
			no.g=nod.g+e.w[i];
			no.h=dist[no.v];
			q.push(no);
		}
	}
	return -1;
}
int main()
{
	int i,a,b,c;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		e.clear();
		e2.clear();
		for(i=1;i<=m;++i)
		{
			scanf("%d%d%d",&a,&b,&c);
			e.add(a,b,c);
			e2.add(b,a,c);
		}
		scanf("%d%d%d",&s,&t,&k);
		spfa();
		printf("%d\n",a_star());
	}
	return 0;
}
82行是因为   下面的算法会认为s==t不走是最短    而题意不是这样  必须走  所以就要求k+1短了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值