简洁题面
(其实翻译我也没看懂orz)
- 第一行给出N(点数),M(边数)。
- 下面的M行每行给出三个数Ai,Bi,Ti,表示从A到B有一条权值为T的单向边。
- 最后给出S,T,K,表示求S到T的第K短路。
- special:
- 起点与终点相同时,S–>S (d=0) 不能算作一条路。
- 题目会给出多组数据。
- 即使有好几条路到T的距离都相同,它们仍被记为不同的路。
正解
A*算法
记g[i]为起点S到i的距离,h[i](期望值)为终点T到i的最短路,用SPFA处理出来。dij从S开始处理,每次从堆中弹出h[i]+g[i]最小的点。
当终点T被弹出第K次时,此时的g[i]即为S到T的第K短路;
下面粘代码片QwQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
int N,M,A,B,T,s,t,K,cnt,ans;
int h[1010],in[1010];
int first[1010],next[100010];
struct maple{
int f,t,d;
}Rode[100010];
struct Edge{
int num,g,h;
bool operator <(const Edge &a)const{
return a.h+a.g<h+g;
}
};
void SPFA()
{
queue<int> q;
memset(h,63,sizeof(h));
memset(in,0,sizeof(in));
q.push(t);
h[t]=0;
in[t]=1;
while(!q.empty())
{
int a=q.front();
q.pop();
in[a]=0;
for(int i=first[a];i;i=next[i])
if(h[Rode[i].t]>h[a]+Rode[i].d)
{
h[Rode[i].t]=h[a]+Rode[i].d;
if(!in[Rode[i].t])
{
q.push(Rode[i].t);
in[Rode[i].t]=1;
}
}
}
}
int search()
{
if(h[s]>10000010) return -1;
if(s==t) ++K;
priority_queue<Edge> q;
q.push((Edge){s,0,h[s]});
int k=0;
while(!q.empty())
{
Edge a=q.top();
q.pop();
if(a.num==t)
{
++k;
if(k==K) return a.g;
}
for(int i=first[a.num];i;i=next[i])
q.push((Edge){ Rode[i].t,a.g+Rode[i].d,h[Rode[i].t]});
}
return -1;
}
void build(int f,int t,int d)
{
Rode[++cnt]=(maple){f,t,d};
next[cnt]=first[f];
first[f]=cnt;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
cnt=0;
memset(first,0,sizeof(first));
memset(next,0,sizeof(next));
for(int i=1;i<=M;++i)
{
scanf("%d%d%d",&A,&B,&T);
build(B,A,T);
}
scanf("%d%d%d",&s,&t,&K);
SPFA();
memset(first,0,sizeof(first));
memset(next,0,sizeof(next));
cnt=0;
for(int i=1;i<=M;++i)
{
build(Rode[i].t,Rode[i].f,Rode[i].d);
}
ans=search();
printf("%d\n",ans);
}
return 0;
}