逃跑(escape)
时间限制:
1
S
e
c
1 Sec
1Sec 内存限制:
128
M
B
128 MB
128MB
因为门卫红美玲的失误,疏忽将入侵者放入了红魔馆。入侵者袭击了红魔馆的大小姐蕾米莉亚·斯卡雷特,大小姐在施放【必杀·斯卡雷特家绝技·抱头蹲防】无效后只好变成了好多蝙蝠,在红魔馆中分散开来。
现在的当务之急是找到二小姐芙兰朵露·斯卡雷特,并且与大小姐化身成的所有蝙蝠集合在一点。你的任务就是帮她们找一条最佳路线。
我们可以用一个无向图来表示红魔馆的地图。蝙蝠和二小姐走过任何一条边都要付出一定的代价。因为形态不同,蝙蝠和二小姐走同一条边付出的代价可能不同。但是如果某一只蝙蝠与二小姐碰面,那么二小姐由于蝙蝠的引导,以后的所有路程可以不支付代价。(也就是相当于二小姐和某只蝙蝠都走到某点,之后无视二小姐的存在。)现在已知所有蝙蝠,二小姐和目标集合点的位置,请你求出所有蝙蝠和二小姐行走代价的和的最小值。
输入
第一行是 5 5 5个正整数, n , m , k , S , T n,m,k,S,T n,m,k,S,T,分别代表无向图点数,边数,蝙蝠的数量,二小姐所在起点的编号,目标点的编号。
第二行是 k k k个正整数,分别代表大小姐每个蝙蝠所在的起点的编号。
接下来有 m m m行,每行有 4 4 4个正整数, u , v , q , p u,v,q,p u,v,q,p,分别是该边的起点、终点,蝙蝠通过该路花费的代价,二小姐通过该路花费的代价。
输出
一行,一个整数,所有人物达到终点所需要的代价的和的最小值。
数据范围
- 对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 200 1≤n≤200 1≤n≤200。
- 对于 另外 20 % 20\% 20% 的数据, S = T S=T S=T。
- 对于 另外 20 % 20\% 20% 的数据, 1 ≤ k ≤ 5 , 1 ≤ n ≤ 1000 , 1 ≤ m ≤ 10000 1≤k≤5,1≤n≤1000,1≤m≤10000 1≤k≤5,1≤n≤1000,1≤m≤10000。
- 对于 100% 的数据,
1
≤
n
≤
10000
,
1
≤
m
≤
100000
,
1
≤
k
≤
10000
,
1
≤
S
,
T
,
u
,
v
≤
n
,
1
≤
p
,
q
≤
1000
1≤n≤10000,1≤m≤100000,1≤k≤10000,1≤S,T,u,v≤n,1≤p,q≤1000
1≤n≤10000,1≤m≤100000,1≤k≤10000,1≤S,T,u,v≤n,1≤p,q≤1000
不保证蝙蝠起点互不相等,数据中可能有重边和自环,保证所有点均能走到 T T T 点(即不存在无解情况)。
题解:
很好的一道最短路的应用题。
最朴素的想法:
由于每只蝙蝠的路是少不了的,那么肯定是二小姐先到某个点,然后蝙蝠接着二小姐到终点。于是考虑枚举每一个二小姐与蝙蝠相遇的位置,用最短路求出每只蝙蝠到每个点的最短路,再从起点和终点走一遍即可。
这样显然过不去,考虑优化求蝙蝠的部分。
先求出二小姐到每个点的最短路,和蝙蝠从每个点到终点的最短路。
蝙蝠可能先到其他更远的一个点,再把二小姐接回来,对于这只蝙蝠,要多走的路就是两个位置的最短路之差,于是要让这个差最小。
于是多建一个虚点,从虚点到每个蝙蝠连一条负的最短路的边,这样从虚点往每个点跑的最短路就是多走的路了。
#include<bits/stdc++.h>
using namespace std;
#define in inline
#define re register
#define rep(i,a,b) for(re int i=a;i<=b;i++)
#define repd(i,a,b) for(re int i=a;i>=b;i--)
#define For(i,a,b) for(re int i=a;i<b;i++)
#define Ford(i,a,b) for(re int i=a;i>b;i--)
#define _(d) while(d(isdigit(ch=getchar())))
template <class T> in void g(T &t) {T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
const int N=1e6+4;
#define inf 1e17
typedef long long ll;
struct E{
int to,nxt,w1,w2;
}e[N<<1];
int n,m,k,s,t,bat[N];bool vis[N];
int head[N],tot;ll d1[N],d2[N],d3[N];
in void ins(int x,int y,int a,int b){
e[++tot]=E{y,head[x],a,b};head[x]=tot;
}
typedef pair<ll,int>P;
#define mk(a,b) make_pair(a,b)
#define fi first
#define se second
in void dj(int st,ll *d,int op){
priority_queue<P,vector<P>,greater<P> >q;
q.push(mk(0,st));ll dis;
rep(i,1,n+1) d[i]=inf;d[st]=0;
memset(vis,0,sizeof(vis));
while(!q.empty()){
int x=q.top().se;q.pop();
if(vis[x]) continue; vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
if(op) dis=e[i].w1;
else dis=e[i].w2;
if(d[e[i].to]>d[x]+dis){
d[e[i].to]=d[x]+dis;
q.push(mk(d[e[i].to],e[i].to));
}
}
}
}
int main(){
//freopen(".in","r",stdin);freopen(".out","w",stdout);
g(n),g(m),g(k),g(s),g(t);
rep(i,1,k) g(bat[i]);
rep(i,1,m){
int x,y,a,b;g(x),g(y),g(a),g(b);
ins(x,y,a,b);ins(y,x,a,b);
}
dj(t,d1,1); dj(s,d2,0);
rep(i,1,k) ins(n+1,bat[i],-d1[bat[i]],0);
dj(n+1,d3,1);
ll ans=inf;
rep(i,1,n) ans=min(ans,d1[i]+d2[i]+d3[i]);
rep(i,1,k) ans+=d1[bat[i]];
printf("%lld\n",ans);
return 0;
}