Description
给出一张n个点m条边的无向图,问从s到t的路径中第k短的路径长度
Input
第一行两个整数n和m表示点数和边数,之后m行每行三个整数a,b,c表示a点和b点之间有一条权值为c的边,之后三个整数s,t,k表示求s到t的k短路
Output
输出从s到t的路径中第k短的路径长度
Sample Input
2 2
1 2 5
2 1 4
1 2 2
Sample Output
14
Solution
k短路,spfa+A*求解
设估价函数f(p)=g(p)+h(p),其中g(p)为当前从s到该点的路径长度,h(p)为该点到t的最短路(在原图的反图上以t为起点做一遍spfa可以得到),那么在bfs这张图时当终点出队列k次时g(t)即为第k短路长度
注意当s=t时需要计算k+1短路,因为s到t这条距离为0的路不算在k短路之中
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1111
#define maxm 111111
struct Edge
{
int to,next,c;
}edge1[maxm],edge2[maxm];
int head1[maxm],tot1,head2[maxn],tot2;
int dis[maxn];
struct node
{
int to,g,f;
bool operator < (const node &a)const
{
if(a.f==f)return a.g<g;
return a.f<f;
}
};
void init()
{
tot1=tot2=0;
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
}
void add(int u,int v,int c)
{
edge1[tot1].c=c;
edge1[tot1].to=v;
edge1[tot1].next=head1[u];
head1[u]=tot1++;
edge2[tot2].c=c;
edge2[tot2].to=u;
edge2[tot2].next=head2[v];
head2[v]=tot2++;
}
void spfa(int s,int V)
{
bool vis[maxn];
memset(vis,false,sizeof(vis));
queue<int>que;
for(int i=0;i<=V;i++)dis[i]=INF;
dis[s]=0;
vis[s]=true;
que.push(s);
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=false;
for(int i=head2[u];i!=-1;i=edge2[i].next)
{
int v=edge2[i].to;
int c=edge2[i].c;
if(dis[v]>dis[u]+c)
{
dis[v]=dis[u]+c;
if(!vis[v])
{
vis[v]=true;
que.push(v);
}
}
}
}
}
int kth_length(int s,int t,int k)
{
node e,temp;
int cnt=0;
priority_queue<node>que;
if(s==t)k++;
if(dis[s]==INF)return -1;
e.to=s,e.g=0,e.f=dis[s];
que.push(e);
while(!que.empty())
{
e=que.top();
que.pop();
if(e.to==t)cnt++;
if(cnt==k)return e.g;
for(int i=head1[e.to];~i;i=edge1[i].next)
{
temp.to=edge1[i].to;
temp.g=e.g+edge1[i].c;
temp.f=temp.g+dis[temp.to];
que.push(temp);
}
}
return -1;
}
int main()
{
int n,m,u,v,c,s,t,k;
while(~scanf("%d%d",&n,&m))
{
init();
while(m--)
{
scanf("%d%d%d",&u,&v,&c);
add(u,v,c);
}
scanf("%d%d%d",&s,&t,&k);
spfa(t,n);
int ans=kth_length(s,t,k);
printf("%d\n",ans);
}
return 0;
}