Chairman of the shortest path tree +
Direct shortest run is the answer, but the right side is too large, but because the right side is $ 2 $ integer power, maintain the right side with the Chairman of the tree.
Maintenance point with the shortest distance of each segment tree weights, each position is $ 0 or $ $ $ 1, a segment tree represents a string of hexadecimal $ 2 $.
The question is how to compare the size of two numbers.
For each node maintains a hash value, when compared to the first query a bit to compare different size, compare the hash value.
Consider modifying carry, violence modifications.
Complexity $ (nlog ^ 2n) O $
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 1005, P = 1e9 + 7; int n, m, cnt = 1, S, T, mx; struct edge { int nxt, to, w; } e[maxn * 2]; vector<int> path; int h[maxn], rt[maxn], f[maxn], pree[maxn * 2]; void link(int u, int v, int w) { e[++cnt].nxt = h[u]; h[u] = cnt; e[cnt].to = v; e[cnt].w = w; } namespace { int Pool = 0; struct node { int lc, rc, h; } t[maxn * 150]; int update(int l, int r, int &x, int y, int p) { t[x = ++Pool] = t[y]; if(l == r) { t[x].h = t[y].h ^ 1; return t[x].h; } int mid = l + r >> 1, ret; if(p <= mid) { ret = update(l, mid, t[x].lc, t[y].lc, p); if(!ret) ret = update(mid + 1, r, t[x].rc, t[y].rc, mid + 1); } else ret = update(mid + 1, r, t[x].rc, t[y].rc, p); t[x].h = (1LL * t[t[x].rc].h * f[mid - l + 1] % P + t[t[x].lc].h) % P; return ret; } } bool cmp(int l, int r, int x, int y) { if(l == r) return t[x].h > t[y].h; int mid = l + r >> 1; if(t[t[x].rc].h == t[t[y].rc].h) return cmp(l, mid, t[x].lc, t[y].lc); return cmp(mid + 1, r, t[x].rc, t[y].rc); } struct data { int rt, x; data() {} data(int _rt, int _x) : rt(_rt), x(_x) {} bool friend operator < (const data &a, const data &b) { return cmp(0, mx, a.rt, b.rt); } }; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) { int u, v, w; scanf("%d%d%d", &u, &v, &w); link(u, v, w); link(v, u, w); mx = max(mx, w); } mx += 100; f[0] = 1; for(int i = 1; i < maxn; ++i) f[i] = 1LL * f[i - 1] * 2 % P; priority_queue<data> q; scanf("%d%d", &S, &T); q.push(data(0, S)); while(!q.empty()) { data t = q.top(); q.pop(); int u = t.x; if(t.rt != rt[u]) continue; if(t.x == T) break; for(int i = h[u]; i; i = e[i].nxt) { int RT = 0; update(0, mx, RT, t.rt, e[i].w); if(!rt[e[i].to] || cmp(0, mx, rt[e[i].to], RT)) { rt[e[i].to] = RT; pree[e[i].to] = i; q.push(data(RT, e[i].to)); } } } if(!pree[T] && S != T) return puts("-1"); int ans = 0, x = T; while(x != S) { ans = (ans + f[e[pree[x]].w]) % P; path.push_back(x); x = e[pree[x] ^ 1].to; } path.push_back(S); reverse(path.begin(), path.end()); printf("%d\n%d\n", ans, path.size()); for(int i = 0; i < path.size(); ++i) printf("%d ", path[i]); return 0; }