乌拉乌拉国有n个城市和m条道路,城市编号为1∼n。由于乌拉乌拉国每一个城市都在创城(创建文明城市),因此,城市之间的道路通行施行道路交通管制:
已知从城市ui到城市vi的道路,需要时间ti。但是一旦当道路管理员进入某条道路后,任何人在道路管理员未驶出该道路前不允许进入该道路。例如:道路管理员在第4时刻进入该道路,在路上需要花费3时,那么在第4∼6时刻不允许其他人进入改街道,只能第7时刻及其以后进入或者在第4时刻之前进入。
现在,计算鸭知道,道路管理员从0时刻出发,依次经过g个城市,计算鸭从时刻k出发,从城市a前往城市b。请问,计算鸭最少需要多长时间。
输入格式:
输入的第一行给出两个整数n,m——表示城市的数量和道路的数量。
输入的第二行给出四个整数a,b,k,g——a,b分别表示计算鸭的初始城市和目的城市;k表示计算鸭出发时刻;g表示道路管理员需要经过的城市数量。
输入的第三行给出g个整数xi——表示道路管理员需要经过的城市编号。
接下来m行,每行3个整数ui,vi,ti——表示从ui至vi需要用时ti
2≤n≤103
2≤m≤104
1≤a,b,ui,vi≤n
0≤k,g≤103
1≤ti≤103
输出格式:
输出一个整数——表示计算鸭从a城市到b城市的最短用时。
输入样例:
6 5
1 6 20 4
5 3 2 4
1 2 2
2 3 8
2 4 3
3 6 10
3 5 15
输出样例:
21
输入样例:
8 9
1 5 5 5
1 2 3 4 5
1 2 8
2 7 4
2 3 10
6 7 40
3 6 5
6 8 3
4 8 4
4 5 5
3 4 23
输出样例:
40
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB
栈限制
8192 KB
注意:本题默认管理员走的点相互之间有且仅有一条边
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define PII pair<int,int>
#define fi first
#define pb push_back
#define sec second
#define endl '\n'
#define INF 0x3f3f3f3f
const int N=2e5+10;
const int M=1e6+10;
map<int,map<int,PII> >mp;
//来存储管理员占用一段道路的时间
int n,m,k,T,a,b,g;
int go[N],dis[N];
//go数组是管理员的路径点
vector<PII>v[N];
//邻接表
void dij(int rt){
memset(dis,0x3f,sizeof dis);
dis[rt]=k;
priority_queue<PII,vector<PII>,greater<PII> >q;
q.push({k,rt});
while(!q.empty()){
int x = q.top().sec;
q.pop();
for(auto i : v[x]){
int e = i.fi;
int w = i.sec ;
if(mp.count(x)&&mp[x].count(e)){
if(dis[x]>=mp[x][e].fi&&dis[x]<=mp[x][e].sec){
// cout << "now dis " << dis[e] << " " << dis[x] << endl;
if(dis[e]>mp[x][e].sec+w){
dis[e]=mp[x][e].sec+w;
q.push({dis[e],e});
}
//这里就是正常迪杰斯特拉,但是要注意如果当前时间是道路被占用时间就不要进,等到占用期过后再进入
}else{
if(dis[e]>dis[x]+w){
dis[e]=dis[x]+w;
q.push({dis[e],e});
}
}
}else{
if(dis[e]>dis[x]+w){
dis[e]=dis[x]+w;
q.push({dis[e],e});
}
}
}
}
}
signed main(){
cin >> n >> m ;
cin >> a >> b >> k >> g ;
for(int i=1;i<=g;i++){
cin >> go[i];
}
for(int i=1;i<=m;i++){
int a1,b1,c1;cin >> a1 >> b1 >> c1;
v[a1].pb({b1,c1});
v[b1].pb({a1,c1});
//建边
}
int la = 0 ;
for(int i=1;i<g;i++){
for(auto j : v[go[i]]){
if(j.first==go[i+1]){
mp[go[i+1]][go[i]]=mp[go[i]][go[i+1]]={la,la+j.second};
la+=j.second;
//两个点之间互相建边
break;
}
}
}
// for(int i=1;i<g;i++){
// cout << mp[go[i]][go[i+1]].fi << " -- " << mp[go[i]][go[i+1]].sec << endl;
// }
dij(a);
cout <<dis[b]-k << endl;
//注意最后输出的是消耗的时间
return 0;
}