此题为一道SPFA的水题,对于不同的起点我们可以求出以其为源点的最短路,之后枚举每一点三段距离之和即可。
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int M=4e4+5;
const int inf=~0u>>1;
ll b,e,p,n,m,top=0;
int f[M];
ll fb[M],fe[M],fn[M];
struct edge{
int nex,to;
}a[M*4];
inline void add(int u,int v){
a[++top]=(edge){f[u],v};
f[u]=top;
}
inline void init(){
for(int i=1;i<=n;++i)
fb[i]=fe[i]=fn[i]=inf;
fb[1]=fe[2]=fn[n]=0;
}
bool inq[M];
queue<int> q1;
void spfa(int x){
bool flag;
memset(inq,false,sizeof(inq));
q1.push(x);
inq[x]=1;
while(!q1.empty()){
int u=q1.front();
for(int i=f[u];i;i=a[i].nex){
int v=a[i].to;
flag=false;
if(x==1){
if(fb[v]>fb[u]+1)
fb[v]=fb[u]+1,flag=true;
}
else if(x==2){
if(fe[v]>fe[u]+1)
fe[v]=fe[u]+1,flag=true;
}
else if(x==n){
if(fn[v]>fn[u]+1)
fn[v]=fn[u]+1,flag=true;
}
if(flag){
if(!inq[v]){
inq[v]=1;
q1.push(v);
}
}
}
q1.pop();
inq[u]=0;
}
}
int main(){
scanf("%lld%lld%lld%lld%lld",&b,&e,&p,&n,&m);
int x,y;
for(int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
init();
spfa(1);
spfa(2);
spfa(n);
ll ans=inf;
for(int i=1;i<=n;++i) //printf("%lld %lld %lld\n",fb[i],fe[i],fn[i]);
ans=min(ans,fn[i]*p+fb[i]*b+fe[i]*e);
printf("%lld",ans);
return 0;
}