blog
k短路
这道题考察的还是 \(A*\) 算法。
首先考虑设立估价函数:当前点到终点的最短路(因为从当前点到终点的所有路径中最短路最短,一定满足 \(\le\))。只需要在反向图上做一遍 dijkstra
就能求得。
然后考虑证明第 \(i\) 次弹出的就是第 \(i\) 短路。类似 \(A*\) 中的证明。
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int N=1001,M=200001;
int n,m,S,T,K,h[N],rh[N],e[M],w[M],ne[M],idx,dist[N],cnt[N];
bool st[N];
void add(int h[],int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
void dijkstra(){
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,T});
memset(dist,0x3f,sizeof dist);
dist[T]=0;
while(heap.size()){
auto t=heap.top();
heap.pop();
int ver=t.y;
if(st[ver])continue;
for(int i=rh[ver];~i;i=ne[i]){
int j=e[i];
if(dist[j]>dist[ver]+w[i]){
dist[j]=dist[ver]+w[i];
heap.push({dist[j],j});
}
}
}
}
int astar(){
priority_queue<PIII,vector<PIII>,greater<PIII>>heap;
heap.push({dist[S],{0,S}});
while(heap.size()){
auto t=heap.top();
heap.pop();
int ver=t.y.y,distance=t.y.x;
++cnt[ver];
if(cnt[T]==K)return distance;
for(int i=h[ver];~i;i=ne[i]){
int j=e[i];
if(cnt[j]<K)heap.push({distance+w[i]+dist[j],{distance+w[i],j}});
}
}
return -1;
}
int main(){
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
memset(rh,-1,sizeof rh);
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(h,a,b,c);
add(rh,b,a,c);
}
scanf("%d%d%d",&S,&T,&K);
if(S==T)++K;
dijkstra();
printf("%d",astar());
return 0;
}