csp-j2023第四题 旅游巴士

旅游巴士这道题在一年之前的csp-j中并没有做(我是一个蒟蒻)
回看本题,又有了新的想法
对于每一层i我们将其看成走到这是的时间j mod k的余数
很显然,为了让我们更快的通过,等待时间+当前时间>=限制时间是最优的

/*
使用分层图,跑dijkstra堆优化的最短路
在限制时间那部分,若小于限制时间,可每次等k的倍数的时间,使得:等待时间+当前时间>=限制时间
因为离开时间是k的倍数,所以我们尽量使每次到达一个点的时间也是k的倍数,这样离开时就不用再等太久了
按照上述思路敲代码是最优的 
vector数组graph是用来存储分层图的,为graph_node类型的 
min_time[i]表示走到分层图的第i个节点的最优时间 
q 是优先队列(堆)priority_queue,是graph_node结构体为类型的,进行重载小于号,方便堆排序 
时间复杂度 O(nk log(nk)) 
*/
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct graph_node{
	int to_node;
	int cur_time;
	bool operator<(const graph_node &s1)const{
		return cur_time>s1.cur_time;
	}
};
vector<graph_node>graph[N];
int n,m,k;
int min_time[N];
void dijkstra(int start){
	for (int i=1;i<=n*k;i++)min_time[i]=0x3f3f3f3f;
	priority_queue<graph_node>q;
	q.push({start,0});min_time[1]=0;
	while (!q.empty()){
		int cur=q.top().to_node,t=q.top().cur_time;q.pop();
		if (t<=min_time[cur]){
			for (const auto&road:graph[cur]){
				int plat=min_time[cur]+1,limt=road.cur_time;
				if (min_time[cur]<limt)plat+=ceil((limt-min_time[cur])*1.0/k)*k;
				if (plat<min_time[road.to_node]){
					min_time[road.to_node]=plat;
					q.push({road.to_node,plat});
				}
			}
		}
	}
}
int main(){
	cin>>n>>m>>k;
	int x,y,len;
	for (int i=1;i<=m;i++){
		cin>>x>>y>>len;
		for (int j=0;j<k;j++)
			graph[j*n+x].push_back({(j+1)%k*n+y,len});
	}
	dijkstra(1);
	if (min_time[n]==0x3f3f3f3f)cout<<-1;
	else cout<<min_time[n];
	return 0;
} 
posted @ 2024-08-11 16:42  just_do_it_now  阅读(134)  评论(0编辑  收藏  举报