problem
游乐场里有 n n n 个娱乐设施,娱乐设施之间有 m m m 条道路相连,经过每一条路都需要花费一定的时间 t t t。每一个娱乐设施旁都会配有一个小卖部,一部分小卖部会销售可乐,另一部分会销售汉堡。
由于大中锋十分贪吃,所以每当他走到一个娱乐设施,他都会先去购买一杯可乐或一个汉堡,并把它们吃掉。但如果大中锋吃掉的汉堡数量比他喝掉的可乐数量多于 k k k,那他就会感到很渴;如果喝掉的可乐数量比吃掉的汉堡数量多于 k k k,那他就会感到很饿。
现在大中锋正在第 a a a 个娱乐设施,他想前往第 b b b 个娱乐设施,但在他前进的路途中他不希望自己很渴或很饿。大中锋想知道自己在路上少花费多少时间。但由于大中锋很懒惰,他不想思考这个问题。你能帮助他解决这个问题吗?
注意:在起始点和终点他也会去买汉堡 / / /可乐,你也需要保证在这两个点他不会感到很饿或者很渴。
数据范围: n ≤ 1 0 4 n≤10^4 n≤104, m ≤ 1 0 5 m≤10^5 m≤105, k ≤ 10 k≤10 k≤10, t ≤ 1 0 4 t≤10^4 t≤104。
solution
我们把可乐的权值赋为 1 1 1,汉堡的权值复赋为 − 1 -1 −1,易知一条合法路径上任意时刻的权值 ∈ [ − k , k ] \in[-k,k] ∈[−k,k]。
那么我们可以设计一个 d p dp dp,设 d [ i ] [ j ] d[i][j] d[i][j] 表示从 a a a 点到 i i i 点权值为 j j j 的最短路径,这可以在 dijkstra 时处理出来。
答案就是 a n s = min i = − k k { d [ n ] [ i ] } ans=\min\limits_{i=-k}^k\{d[n][i]\} ans=i=−kmink{d[n][i]}。
时间复杂度 O ( n log n ) O(n\log n) O(nlogn)。
code
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define M 200005
using namespace std;
int n,m,k,t,p,q;
int val[N],d[N][25],first[N],v[M],w[M],nxt[M];
int Abs(int x) {return x>0?x:-x;}
void add(int x,int y,int z){
nxt[++t]=first[x],first[x]=t,v[t]=y,w[t]=z;
}
struct node{
int x,del,dis;
node(int x=0,int del=0,int dis=0):x(x),del(del),dis(dis){}
};
bool operator<(const node &p,const node &q) {return p.dis>q.dis;}
priority_queue<node>Q;
void dijkstra(int S){
memset(d,0x3f,sizeof(d));
Q.push(node(S,val[S]+k,0)),d[S][val[S]+k]=0;
while(!Q.empty()){
node now=Q.top();Q.pop();
for(int i=first[now.x];i;i=nxt[i]){
int to=v[i],num=now.del+val[to];
if(num<0||num>2*k) continue;
if(d[to][num]>now.dis+w[i]){
d[to][num]=now.dis+w[i];
Q.push(node(to,num,d[to][num]));
}
}
}
}
int main(){
int x,y,z,T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
t=0,memset(first,0,sizeof(first));
for(int i=1;i<=n;++i) scanf("%d",&x),val[i]=(x==1)?1:-1;
for(int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
scanf("%d%d",&p,&q),dijkstra(p);
int ans=0x3f3f3f3f;
for(int i=0;i<=2*k;++i) ans=min(ans,d[q][i]);
printf("%d\n",ans==0x3f3f3f3f?-1:ans);
}
return 0;
}