版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/83864350
题解:
短路裸题,今天看了一下,顺便学习了一发
*的思想。
如果直接暴力做的话,那么就是当
第
次出堆的时候就是答案,但是这样的话
短路上的所有点都要出堆
次,复杂度不能承受。考虑优化,如果一个点的当前距离很短,但是它到终点的距离很长,那么它是不优秀的,所以可以加上一个估价函数,预估他到终点的距离,每次选择当前距离+预估距离最小的元素出堆,这样一来每个点的出堆次数不会太多,即可通过。
值得一提的是估价函数的设置,一开始我用的是当前距离+当前点到终点最短路,我认为这样更加接近实际答案,但是这样MLE了,入堆节点太多,直接用当前点到终点最短路就能AC了。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=1010;
const int Maxm=100010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,m,S,T,k;
struct Edge{int y,d,next;}e[Maxm];
int last[Maxn],len;
void ins(int x,int y,int d)
{
int t=++len;
e[t].y=y;e[t].d=d;e[t].next=last[x];last[x]=t;
}
struct Node
{
int x,t1,t2;
Node(int _x,int _t1,int _t2){x=_x,t1=_t1,t2=_t2;}
};
bool operator < (Node a,Node b){return a.t1+a.t2>b.t1+b.t2;}
int cnt[Maxn],f[Maxn];
void dijkstra()
{
memset(f,63,sizeof(f));f[T]=0;
memset(cnt,0,sizeof(cnt));
priority_queue<Node>q;q.push(Node(T,0,0));
while(!q.empty())
{
Node tmp=q.top();q.pop();
int x=tmp.x;
if(cnt[x])continue;
cnt[x]++;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(f[x]+e[i].d<f[y])
{
f[y]=f[x]+e[i].d;
q.push(Node(y,f[y],0));
}
}
}
}
void kth()
{
memset(cnt,0,sizeof(cnt));
priority_queue<Node>q;q.push(Node(S,0,f[S]));
while(!q.empty())
{
Node tmp=q.top();q.pop();
int x=tmp.x;
cnt[x]++;
if(x==T&&cnt[T]==k){printf("%d",tmp.t1);return;}
if(cnt[x]>k)continue;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
q.push(Node(y,tmp.t1+e[i].d,f[y]));
}
}
puts("-1");
}
int X[Maxm],Y[Maxm],D[Maxm];
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
X[i]=read(),Y[i]=read(),D[i]=read();
ins(Y[i],X[i],D[i]);
}
S=read(),T=read(),k=read();
if(S==T)k++;
dijkstra();
memset(last,0,sizeof(last));len=0;
for(int i=1;i<=m;i++)ins(X[i],Y[i],D[i]);
kth();
}