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;
}
posted @ 2023-05-13 07:20  wscqwq  阅读(7)  评论(0编辑  收藏  举报