2022“杭电杯”中国大学生算法设计超级联赛(5)1003 Slipper
建边需要一些技巧,不然会TLE。一种方式是在每个深度\(d\)新建一个点\(t_d(1\le d\le maxdep)\),对于每个深度为\(d\)的点 \(u_d\),从\(t_d\)向\(u_d\)连一条有向边,再从\(u_d\)向\(t_{d-k}\)和\(t_{d+k}\)连有向边,最后跑一遍dij即可
#include<bits/stdc++.h>
using namespace std;
#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, int> PLI;
typedef unsigned long long ULL;
const int INF = 0X3f3f3f3f, N = 2e6 + 10, M = 4 * N, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);
int n, k, p, start, ed;
int depth[N], maxdep;
int head[N], idx;
struct EGDE {
int to, next, w;
} eg[M];
void add(int x, int y, int w) {
eg[idx].to = y;
eg[idx].next = head[x];
eg[idx].w = w;
head[x] = idx++;
}
void dfs(int cur, int fa, int dep) {
depth[cur] = dep;
maxdep = max(maxdep, dep);
for (int i = head[cur]; ~i; i = eg[i].next) {
int to = eg[i].to;
if (to == fa) continue;
dfs(to, cur, dep + 1);
}
}
LL dis[N];
bool st[N];
void dij() {
priority_queue<PLI, vector<PLI>, greater<PLI> > q;
memset(dis, 0x3f, sizeof dis);
memset(st, 0, sizeof st);
dis[start] = 0;
q.push({0ll, start});
while (!q.empty()) {
auto cur = q.top().se;
q.pop();
if (cur == ed) return;
if (st[cur]) continue;
st[cur] = 1;
for (int i = head[cur]; ~i; i = eg[i].next) {
int to = eg[i].to;
if (dis[to] > dis[cur] + eg[i].w) {
dis[to] = dis[cur] + eg[i].w;
q.push({dis[to], to});
}
}
}
return;
}
void work() {
idx = maxdep = 0;
memset(head, -1, sizeof head);
cin >> n;
rep(i, 2, n) {
int x, y, w;
cin >> x >> y >> w;
add(x, y, w);
add(y, x, w);
}
cin >> k >> p >> start >> ed;
dfs(1, 0, 1);
rep(i, 1, n) {
add(n + depth[i], i, p);
if (depth[i] - k >= 1) add(i, n + depth[i] - k, 0);
if (depth[i] + k <= maxdep) add(i, n + depth[i] + k, 0);
}
dij();
cout << dis[ed] << endl;
}
int main() {
IO
int test = 1;
cin >> test;
while (test--) {
work();
}
return 0;
}