POJ-2449-Remmarguts' Date(第K短路 A* + SPFA)

Remmarguts' Date

Time Limit: 4000MS Memory Limit: 65536K
Total Submissions: 41069 Accepted: 11294

Description

"Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, he told them a story. 

"Prince Remmaguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission." 

"Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)" 

Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister's help! 

DETAILS: UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate. 

Input

The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T. 

The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).

Output

A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output "-1" (without quotes) instead.

Sample Input

2 2
1 2 5
2 1 4
1 2 2

Sample Output

14

题意:给出一个有向图、求起点 s 到终点 t 的第 k 短路、不存在则输出 -1

题意分析:A*算法求第k短路裸题,如果还不会A*算法求第k短路可以去我的博客算法分类中寻找A*算法解释的博客。有从公众号上找到漫画解释,讲的非常详细,特别容易理解,网上的要么是解释一大堆,枯燥乏味,要么代码恶心难以理解

代码:

//具体可见我的博客
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<cmath>
#define M 100005
#define N 1005
#define INF 0x3f3f3f3f
using namespace std;
int n,m,c1,c,st,en,k;
int head[N],head1[N],dis[N];
//dis为从当前点p到终点t的最短路
bool vis[N];
struct ljh
{
	int next,to,w;
}e[M],a[M];
struct xqy
{
	int pos,g,f;//g为从源点s到当前点p所走的路径长度,f为A*算法(也就是类似启发式搜索)的F值
	xqy(int pos=0,int g=0,int f=0):pos(pos),g(g),f(f){}
	bool operator < (const xqy&a)const
	{
		if(a.f==f)return a.g<g;
		return a.f<f;
	}
};
inline void add(int x,int y,int z)
{
	e[c].next=head[x];
	e[c].w=z;
	e[c].to=y;
	head[x]=c++;
}
inline void add1(int x,int y,int z)
{
	a[c1].next=head1[x];
	a[c1].w=z;
	a[c1].to=y;
	head1[x]=c1++;
}
void SPFA(int x)
{
	queue<int>q;
	for(int i=1;i<=n;i++)dis[i]=INF;
	memset(vis,0,sizeof(vis));
	dis[x]=0;
	q.push(x);
	vis[x]=1;
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		// cout<<now<<endl;
		for(int i=head1[now];i!=-1;i=a[i].next)
		{
			int nex=a[i].to;
			// cout<<nex<<endl;
			if(dis[nex]>dis[now]+a[i].w)
			{
				dis[nex]=dis[now]+a[i].w;
				if(!vis[nex])
				{
					q.push(nex);
					vis[nex]=1;				
				}
			}
		}
	}
	return ;
}
int A_star(int st,int en,int k)
{
	int num=0;
	if(st==en)k++;
	if(dis[st]==INF)return -1;
	priority_queue<xqy>q;
	q.push(xqy(st,0,dis[st]));
	while(!q.empty())
	{
		xqy now=q.top();
		q.pop();
		if(now.pos==en)num++;
		if(num==k)return now.g;//相当于走到en点所走的路程
		for(int i=head[now.pos];i!=-1;i=e[i].next)
		{
			xqy nex;
			nex.pos=e[i].to;
			nex.g=now.g+e[i].w;
			nex.f=(now.g+e[i].w)+dis[e[i].to];
			q.push(nex);
		}
	}
	return -1;
}
int main()
{
#ifdef LOCAL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
#endif
	while(~scanf("%d%d",&n,&m))
	{
		c=0;
		c1=0;
		memset(head,-1,sizeof(head));
		memset(head1,-1,sizeof(head1));
		for(int i=1;i<=m;i++)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			add(x,y,z);
			add1(y,x,z);//反向建图
		}		
		scanf("%d%d%d",&st,&en,&k);
		SPFA(en);
		// for(int i=1;i<=n;i++)cout<<dis[i]<<" ";cout<<endl;
		printf("%d\n",A_star(st,en,k));
	}
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值