dis数组里面存到此点的最少需要的等级,没到一个点就对其他点进行松弛操作,太久没写最短路了,松弛操作忘了最重要的一步,levpass是通过u到v此边需要的最少等级,所以dis[v]应该是和到达u点且通过u-v边的最少等级进行松弛,就是这里gg,拿铁一杯~,还有坑点就是双向边数组开两倍,用longlong,输出的时候可能会超。
这个比二分加最短路的快挺多了,就是计蒜客只有20组数据卡不掉,二分加最短路大概要250左右,我的只有60。
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<ctime>
#include<algorithm>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define INF 0x3f3f3f3f
#define endl '\n'
using namespace std;
const int maxn=2e5+10;
const int mod=1e4+7;
ll head[maxn],tot=0,dis[maxn],nod[maxn];
ll n,m,c,d,e;
struct nn
{
ll v,w,nex;
}l[maxn];
struct mm
{
ll u,lev,cnt;
mm(){}
mm(ll _u,ll _lev,ll _cnt):u(_u),lev(_lev),cnt(_cnt){}
bool operator < (const mm & a)const
{
return lev>a.lev;
}
};
void addline(ll u,ll v,ll w)
{
l[tot].nex=head[u];
l[tot].v=v;
l[tot].w=w;
head[u]=tot;
tot++;
}
ll dij()
{
memset(dis,INF,sizeof dis);
memset(nod,0,sizeof nod);
priority_queue<mm>q;
q.push(mm(1,0,0));
dis[1]=0;
while(!q.empty()){
mm now=q.top();
q.pop();
if(nod[now.u])continue;
nod[now.u]=1;
for(ll i=head[now.u];i!=-1;i=l[i].nex){
ll v=l[i].v;
ll levd=l[i].w%d==0 ? l[i].w/d : l[i].w/d+1;
ll levcnt=(now.cnt+1)%e==0 ? (now.cnt+1)/e : (now.cnt+1)/e+1;
ll levpass=max(levd,levcnt);
levpass=max(dis[now.u],levpass);
dis[v]=min(dis[v],levpass);
if(nod[v]==0)q.push(mm(l[i].v,dis[v],now.cnt+1));
}
}
return dis[n];
}
int main()
{
memset(head,-1,sizeof head);
scanf("%lld%lld%lld%lld%lld",&n,&m,&c,&d,&e);
while(m--){
ll a1,a2,a3;
scanf("%lld%lld%lld",&a1,&a2,&a3);
addline(a1,a2,a3);
addline(a2,a1,a3);
}
ll ans=dij();
if(ans==INF)cout<<-1<<endl;
else cout<<ans*c<<endl;
return 0;
}