题目描述:给定一个有向图,计算从起点到终点的第k短路。
很容易想到用BFS+优先队列来做,再一想就想到用A*算法
其中估值函数为此点到终点的最短路。即建反向图做一次spfa
此题看起来很简单,实际上很坑爹 我就是这么WA掉了= =
因为会有重边,而它们权值不同;若起点为终点,最短路不为0,即必须要走……
肿么办?
在出队时再判断是否到达终点,这样保证了先出队的小。
若起点与终点相同,则k++
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define MAXN 1005
#define MAXM 100005
using namespace std;
int n ,m ,a ,b ,c ,be ,en ,k ,h[MAXN] ;
bool in[MAXN] ;
struct node
{
int v ,w ;
node *next ;
}edge[MAXM<<2] ,*num[MAXN] ,*code ,*p ,*num2[MAXN] ;
void SPFA()
{
queue<int>point;
point.push(en);
in[en]=1, h[en]=0;
int u ,v ;
while(!point.empty())
{
u=point.front();
point.pop();
in[u]=0;
for(p=num2[u];p!=NULL;p=p->next)
{
v=p->v;
if(h[v]==-1)
{
h[v]=h[u]+p->w;
point.push(v);
in[v]=1;
}
else if(h[v]>h[u]+p->w)
{
h[v]=h[u]+p->w;
if(!in[v])
{
point.push(v);
in[v]=1;
}
}
}
}
}
struct aaa
{
int pos ,step ;
aaa(){}
aaa(const int a,const int b)
{
pos=a ,step=b ;
}
bool operator < (const aaa a) const
{
return step+h[pos]>a.step+h[a.pos];
}
}t ;
void solve()
{
if(be==en)++k;
priority_queue<aaa>point;
point.push(aaa(be,0));
while(!point.empty())
{
t=point.top();
point.pop();
if(t.pos==en)//特别注意
{
--k;
if(k==0)
{
printf("%d\n",t.step);
return;
}
}
for(p=num[t.pos];p!=NULL;p=p->next)
point.push(aaa(p->v,t.step+p->w));
}
printf("-1\n");
}
int main()
{
while(~scanf("%d%d",&n ,&m ))
{
code=edge;
memset(num,0,sizeof(num));
memset(num2,0,sizeof(num2));
memset(h,-1,sizeof(h));
for(int i=0;i<m;++i)
{
scanf("%d%d%d",&a,&b,&c);
//建正向图
p=++code;
p->v=b ,p->w=c ,p->next=num[a];
num[a]=p;
//建反向图
p=++code;
p->v=a ,p->w=c ,p->next=num2[b];
num2[b]=p;
}
scanf("%d%d%d",&be,&en,&k);
SPFA();
solve();
}
return 0;
}