题意:一张 nnn 个点 mmm 条边的无向图,边带距离,可以坐出租车,花费为距离除以常数 rrr 向上取整;也可以坐公交车,每路车行驶路线给定,无论坐多少站花费都为 cic_ici (每路车可能不同)。qqq 次询问 sss 到 ttt 的最小花费。
n,m≤2×105,q≤10n,m\leq 2\times 10^5,q\leq 10n,m≤2×105,q≤10
对于一路公交车建一个虚点向所有车站连边即可
公交车直接记录余数,在虚点的位置清空。
因为 dijkstra 只需要保证有偏序关系,a,b≤a+ba,b\leq a+ba,b≤a+b ,实际上限制非常松,所以可以保证正确性。
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <utility>
#define MAXN 250005
#define MAXM 1200005
using namespace std;
typedef long long ll;
const int INF=1e9;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
int n,m,k,r,q;
struct dist{ll c;int f;inline dist(const int& c=0,const int& f=0):c(c),f(f){}};
inline dist operator +(const dist& a,const dist& b)
{if (b.f==-1) return dist(a.c+b.c+(a.f>0),0);dist ans(a.c+b.c,max(a.f+b.f,0));if (ans.f>r) ++ans.c,ans.f-=r;return ans;
}
inline bool operator <(const dist& a,const dist& b){return a.c==b.c? a.f<b.f:a.c<b.c;}
struct edge{int u,v;dist w;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt;
inline void addnode(int u,int v,dist w)
{e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt;
}
dist dis[MAXN];
typedef pair<dist,int> pi;
void dij(int s)
{for (int i=1;i<=n+k;i++) dis[i]=dist(INF);dis[s]=dist(0);priority_queue<pi,vector<pi>,greater<pi> > q;q.push(make_pair(dis[s],s));while (!q.empty()){int u=q.top().second;q.pop();for (int i=head[u];i;i=nxt[i])if (dis[u]+e[i].w<dis[e[i].v]){dis[e[i].v]=dis[u]+e[i].w;q.push(make_pair(dis[e[i].v],e[i].v));}}
}
int main()
{n=read(),m=read(),k=read(),r=read(),q=read();for (int i=1;i<=m;i++){int u,v,w;u=read(),v=read(),w=read();dist t=dist(w/r,w%r);addnode(u,v,t),addnode(v,u,t);}for (int i=1;i<=k;i++){int t,c;t=read(),c=read();while (t--){int u=read();addnode(u,n+i,dist());addnode(n+i,u,dist(c,-1));}}while (q--){int s,t;s=read(),t=read();dij(s);printf("%lld\n",dis[t].c+(dis[t].f>0));}return 0;
}