Dane jest
Mamy też
W tym podzadaniu rozmiar podzbioru
Wystarczy zatem odpowiadać na zapytania: „jeśli usuniemy krawędź
Przynależność wierzchołka do poddrzewa jest klasycznym problemem na drzewie, który
można rozwiązać przy pomocy DFS-a.
Dla każdego wierzchołka
Poniższy algorytm implementuje rozwiązanie w czasie
const int N = 110000; int n,s,q,root,shop[N]; vector<pii> adj[N]; int ea[N],eb[N],ew[N]; int lev[N],tin[N],tout[N],T; void dfs(int v, int par, int l) { lev[v] = l; tin[v] = T++; for (auto [u, w] : adj[v]) if (u != par) { dfs(u, v, l+1); } tout[v] = T; } bool is_desc(int v, int w) { return tin[v] <= tin[w] && tout[w] <= tout[v]; } int main() { scanf("%d%d%d%d",&n,&s,&q,&root); --root; REP(i,n-1) { int a,b,w; scanf("%d%d%d",&a,&b,&w); --a; --b; adj[a].emplace_back(b, w); adj[b].emplace_back(a, w); ea[i] = a; eb[i] = b; ew[i] = w; } REP(i,s) { int a; scanf("%d",&a); --a; shop[a] = 1; } dfs(root, -1, 0); for (int i=0; i<q; ++i) { int r,a; scanf("%d%d",&r,&a); --r; --a; int vb = lev[ea[r]] < lev[eb[r]] ? eb[r] : ea[r]; if (is_desc(vb, a)) { printf("0\n"); } else { printf("escaped\n"); } } }
W przypadku nietrywialnego zbioru
Część wierzchołków z
Załóżmy zatem, że
Podsumowując, odpowiedzią na zapytanie jest
Wszystkie wartości
const int N = 110000, LOGN = 17; const ll infty = 1e18; int n,s,q,root,shop[N]; vector<pii> adj[N]; int ea[N],eb[N],ew[N]; int lev[N],tin[N],tout[N],T; ll down[N]; int parent[N],pw[N]; int jmp[LOGN][N]; ll jmp_w[LOGN][N], jmp_c[LOGN][N]; void dfs(int v, int par, int l) { lev[v] = l; tin[v] = T++; down[v] = shop[v] ? 0 : infty; parent[v] = par; for (auto [u, w] : adj[v]) if (u != par) { dfs(u, v, l+1); pw[u] = w; down[v] = min(down[v], w + down[u]); } tout[v] = T; } bool is_desc(int v, int w) { return tin[v] <= tin[w] && tout[w] <= tout[v]; } int main() { scanf("%d%d%d%d",&n,&s,&q,&root); --root; REP(i,n-1) { int a,b,w; scanf("%d%d%d",&a,&b,&w); --a; --b; adj[a].emplace_back(b, w); adj[b].emplace_back(a, w); ea[i] = a; eb[i] = b; ew[i] = w; } REP(i,s) { int a; scanf("%d",&a); --a; shop[a] = 1; } dfs(root, n, 0); parent[n] = n; REP(i,n+1) { jmp[0][i] = parent[i]; jmp_w[0][i] = pw[i]; jmp_c[0][i] = pw[i] + down[parent[i]]; } REP(f,LOGN-1) { REP(i,n+1) { int mid = jmp[f][i]; jmp[f+1][i] = jmp[f][mid]; jmp_w[f+1][i] = jmp_w[f][i] + jmp_w[f][mid]; jmp_c[f+1][i] = min( jmp_c[f][i], jmp_w[f][i] + jmp_c[f][mid] ); } } for (int i=0; i<q; ++i) { int r,a; scanf("%d%d",&r,&a); --r; --a; int vb = lev[ea[r]] < lev[eb[r]] ? eb[r] : ea[r]; if (is_desc(vb, a)) { ll ans = down[a], len = 0; int v = a; int dist = lev[v] - lev[vb]; REP(f,LOGN) if (dist & 1<<f) { ans = min(ans, len + jmp_c[f][v]); len += jmp_w[f][v]; v = jmp[f][v]; } if (ans == infty) { printf("oo\n"); } else { printf("%lld\n", ans); } } else { printf("escaped\n"); } } }
Złożoność czasowa rozwiązania to