题目描述
小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家。
该国有N个城市,城市之间有道路相连。一共有M条双向道路。保证没有自环和重边。
K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入。由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市。换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险。
小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略。小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所以晚上要住旅店。安全的的城市旅馆比较便宜要P元,而被危险的城市,旅馆要进行安保措施,所以会变贵,为Q元。所有危险的城市的住宿价格一样,安全的城市也是。在1号城市和N城市,不需要住店。
小a比较抠门,所以他希望知道从1号城市到N号城市所需要的最小花费。
输入数据保证存在路径,可以成功逃离。输入数据保证他可以逃离成功。
输入格式
第一行4个整数(N,M,K,S)
第二行2个整数(P,Q)
接下来K行,ci,表示僵尸侵占的城市
接下来M行,ai,bi,表示一条无向边
输出格式
一个整数表示最低花费
首先我们需要知道哪些城市是危险的:
根据广搜的性质(第一次搜到的答案就是最优值),我们将被占领的城市入队,然后用广搜将它们拓展从而求出与最近被占城市距离在S以内的城市。
然后我们需要计算最短路:
安全的城市点权就是P,危险的就是Q,而被占领的城市不能去,干脆让点权变成inf。然后用Dijkstra即可。
时间复杂度为O((N+M)log(N+M))。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define maxn 100001
#define maxm 200001
#define inf 0x3f3f3f3f
using namespace std;
int n,m,K,S,P,Q;
inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
struct edge{
int to,next;
edge(){}
edge(const int &_to,const int &_next){ to=_to,next=_next; }
}e[maxm<<1];
int head[maxn],k;
inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; }
int val[maxn];
bool vis[maxn];
queue< pair<int,int> > que;
inline void bfs(){
while(que.size()){
int u=que.front().first,w=que.front().second; que.pop();
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(!vis[v]&&w+1<=S) que.push(make_pair(v,w+1)),vis[v]=true;
}
}
}
long long dis[maxn];
bool used[maxn];
priority_queue< pair<long long,int>,vector< pair<long long,int> >,greater< pair<long long,int> > > q;
inline void Dijkstra(){
memset(dis,0x3f,sizeof dis);
q.push(make_pair(0,1)),dis[1]=0;
while(q.size()){
int u=q.top().second; q.pop();
if(used[u]) continue; used[u]=true;
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(dis[v]>dis[u]+val[v]) dis[v]=dis[u]+val[v],q.push(make_pair(dis[v],v));
}
}
}
int main(){
memset(head,-1,sizeof head);
n=read(),m=read(),K=read(),S=read(),P=read(),Q=read();
for(register int i=1;i<=K;i++){
int x=read();
que.push(make_pair(x,0)),val[x]=inf,vis[x]=true;
}
for(register int i=1;i<=m;i++){
int u=read(),v=read();
add(u,v),add(v,u);
}
bfs();
for(register int i=1;i<=n;i++){
if(vis[i]&&!val[i]) val[i]=Q;
if(!vis[i]) val[i]=P;
}
val[1]=val[n]=0;
Dijkstra();
printf("%lld
",dis[n]);
return 0;
}