wdnmd真就自闭了,上次数组开小1扣了15分痛失阿珂,这次一样扣了15分。
对于出租车类型为1的边,连边方式同普通无向图。
对于公交车连类型为2的边,建两个虚点1和2,先把所有站点向虚点1连边权为0的单向边,再从虚点1向虚点2连边权为c的单向变,再从虚点2向所有站点连边权为c的单向边。
这样每次就从a开始跑dijkstra。
但是注意到题目的计费方式出租车和公交车不同,所以要对距离开结构体dis表示当前距离为k*r+p。
这样可以重载加号和小于号来做到连续坐出租车的更新,当出现一条类型为2的边,把距离的p设为0,即从出租车上下来了上了公交车即可。
注意因为新建了虚点和新连了边,所以数组要略微开大一些。
/*
_______ ________ _______
/ _____ \ / ______ \ / _____ \
/ / \_\ _ __ _ / / \ \ _ __ _ / / \_\
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | __ | | | | | | | | | |
| | __ \ \ | | / / | | \ \| | \ \ | | / / | | __
\ \_____/ / \ \/ /\ \/ / \ \_____\ / \ \/ /\ \/ / \ \_____/ /
\_______/ \___/ \___/ \______/\__\ \___/ \___/ \_______/
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define ll long long
const int INF = 1e18;
const int N = 200000;
int n, m, head[N * 2 + 50], q, cnt, num;
ll k, r;
struct Dis
{
ll k, p;
bool operator < (const Dis &rhs) const
{
if (rhs.k == k) return p < rhs.p;
else return k < rhs.k;
}
Dis operator + (const Dis &rhs) const
{
Dis tmp = (Dis){0, 0};
tmp.k = k + rhs.k + (p + rhs.p) / r;
tmp.p = (p + rhs.p) % r;
return tmp;
}
bool operator != (const Dis &rhs) const
{
return rhs.k != k || rhs.p != p;
}
} dis[N * 2 + 50];
struct Nod
{
Dis dis;
int id;
bool operator < (const Nod &rhs) const
{
return rhs.dis < dis;
}
};
struct Node
{
int next, to, typ;
ll dis;
} edge[N * 4 + 50];
void Addedge(int u, int v, ll w, int typ)
{
edge[++num] = (Node){head[u], v, typ, w};
head[u] = num;
return;
}
template <class T>
void Read(T &x)
{
x = 0; int p = 0; char st = getchar();
while (st < '0' || st > '9') p = (st == '-'), st = getchar();
while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
x = p ? -x : x;
return;
}
void Dijkstra(int s)
{
priority_queue<Nod> q;
for (int i = 1; i <= cnt; i++) dis[i] = (Dis){INF, 0};
dis[s] = (Dis){0, 0};
q.push((Nod){dis[s], s});
while (!q.empty())
{
Nod u = q.top(); q.pop();
if (u.dis != dis[u.id]) continue;
for (int i = head[u.id]; i; i = edge[i].next)
{
int v = edge[i].to;
Dis tmp = dis[u.id];
if (edge[i].typ == 1) tmp = tmp + (Dis){edge[i].dis / r, edge[i].dis % r};
else
{
tmp.k += (tmp.p > 0);
tmp.p = 0;
tmp = tmp + (Dis){edge[i].dis, 0};
}
if (tmp < dis[v])
{
dis[v] = tmp;
q.push((Nod){dis[v], v});
}
}
}
return;
}
int main()
{
Read(n); Read(m); Read(k); Read(r); Read(q); cnt = n;
ll d;
for (int i = 1, u, v; i <= m; i++)
{
Read(u); Read(v); Read(d);
Addedge(u, v, d, 1); Addedge(v, u, d, 1);
}
for (int i = 1, t; i <= k; i++)
{
ll c;
Read(t); Read(c);
cnt++; int tmp = cnt; cnt++;
for (int j = 1, x; j <= t; j++)
Read(x), Addedge(x, tmp, 0, 2), Addedge(cnt, x, 0, 2);
Addedge(tmp, cnt, c, 2);
}
int a, b;
while (q--)
{
Read(a); Read(b);
Dijkstra(a);
printf("%lld\n", dis[b].k + (dis[b].p > 0));
}
return 0;
} 
京公网安备 11010502036488号