k短路-洛谷P2483 [SDOI2010]魔法猪学院
https://daniu.luogu.org/problem/show?pid=2483
A*求k短路和dijkstra算法很相似。
我们先把边反向,预处理出h(x),表示从x到T的最短路径长度。
另g(x)为目前为止从起点到x的距离。
以(h(x)+g(x))为关键字维护一个小根堆,然后跑dijkstra即可。
第k次到达终点的时候输出。
正确性显然。
这个是我们xxy学长给我们讲的,其实已经很明了了;
当然Fop_zz的博客有详细的介绍;
这里
我就不多说了;
然后SPFA炸了;
改好就AC了;
这;
当然内存是在bz过不了的;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<queue>
#define Ll long long
using namespace std;
double h[5010];
struct T{
int x;
double v;
bool operator < (const T &a) const
{
return a.v+h[a.x]<v+h[x];
}
};
priority_queue<T>Q;
struct cs{
int to,next;
double v;
}a[200010];
struct In{
int x,y;
double z;
}r[200010];
int head[5010],ll;
int q[400010];
bool vi[5010];
int n,m,ans;
double money;
void init(int x,int y,double z){
a[++ll].to=y;
a[ll].v=z;
a[ll].next=head[x];
head[x]=ll;
}
void SPFA(int S){
int l=0,r=1;
q[1]=S;
for(int i=0;i<=n;i++)h[i]=1e9;
h[S]=0;
while(r>l){
int x=q[++l];
for(int k=head[x];k;k=a[k].next)
if(a[k].v+h[x]<h[a[k].to]){
h[a[k].to]=a[k].v+h[x];
if(!vi[a[k].to]){
vi[a[k].to]=1;
q[++r]=a[k].to;
}
}
vi[x]=0;
}
}
void Dijkstra(int S,int E){
T c;
c.v=0;
c.x=S;
Q.push(c);
while(!Q.empty()){
c=Q.top();
Q.pop();
if(c.x==E){
money-=c.v;
if(money<0)return;
ans++;
}
for(int k=head[c.x];k;k=a[k].next){
T p;
p.x=a[k].to;
p.v=c.v+a[k].v;
Q.push(p);
}
}
}
int main(){
scanf("%d%d%lf",&n,&m,&money);
for(int i=1;i<=m;i++){
scanf("%d%d%lf",&r[i].x,&r[i].y,&r[i].z);
init(r[i].y,r[i].x,r[i].z);
}
SPFA(n);
memset(head,0,sizeof head);
ll=0;
for(int i=1;i<=m;i++)init(r[i].x,r[i].y,r[i].z);
Dijkstra(1,n);
printf("%d",ans);
}