kruskal重构树?

P4185 [USACO18JAN] MooTube G

啊?这么复杂,这不是并查集吗。。。
by Fractured_Angel @ 2023-11-11 18:28:57


@[the_long_way_to_dp](/user/837888) 重构树可以在线做。
by lzyqwq @ 2023-11-11 18:32:01


@[Ailuomangacencei](/user/426187) $(sz_u+1)/2$ 我不知道对不对,你其实可以直接维护每个子树的叶子个数的
by lzyqwq @ 2023-11-11 18:32:48


哦,纠正一下,我忘记减去自己了,所以应该是(sz[u] - 1) / 2 (大概?)
by Ailuomangacencei @ 2023-11-11 18:39:12


求助,T了第8个点 ```cpp #include <bits/stdc++.h> using namespace std; const int N = 2e5 + 5; int n, Q; int fa[N], top[N], sz[N], nw[N]; struct E{ int u, v, w; bool operator < (const E &x) const { return w > x.w; } }edge[N];int idx; inline int find_top(int x){ if (x == top[x]) return x; return top[x] = find_top(top[x]); } void EK_kruskal(){ for (int i = 0;i < n * 2; ++ i){ top[i] = i; sz[i] = 1; } for (int i = 1;i < n; ++ i){ int u = edge[i].u, v = edge[i].v, w = edge[i].w; if (find_top(u) == find_top(v)) continue; int nwp = n + i; nw[nwp] = w; sz[nwp] += sz[top[u]] + sz[top[v]]; fa[top[u]] = fa[top[v]] = nwp; top[top[u]] = top[top[v]] = nwp; } } inline void add(int u, int v, int w){ edge[++idx].u = u; edge[idx].v = v; edge[idx].w = w; } int main(){ scanf("%d%d", &n, &Q); for (int i = 1;i < n; ++ i){ int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u, v, w); } sort(edge + 1, edge + n); EK_kruskal(); fa[0] = n * 2; nw[n * 2] = -1; while (Q --){ int k, v;scanf("%d%d", &k, &v); while (nw[fa[v]] >= k) v = fa[v]; printf("%d\n", (sz[v] - 1) >> 1); } return 0; } ``` gg,这怎么被卡的 其他点都是100ms以下
by Ailuomangacencei @ 2023-11-11 19:11:46


警钟长鸣吧 好像确实可以把重构树卡成一条链
by Ailuomangacencei @ 2023-11-11 19:14:09


是时候请出倍增来优化了
by Ailuomangacencei @ 2023-11-11 19:15:09


OK,倍增解决 给大家分享一下 ```cpp #include <bits/stdc++.h> using namespace std; const int N = 2e5 + 5; int n, Q; int fa[N][20], top[N], sz[N], nw[N]; struct E{ int u, v, w; bool operator < (const E &x) const { return w > x.w; } }edge[N];int idx; inline int find_top(int x){ if (x == top[x]) return x; return top[x] = find_top(top[x]); } void EK_kruskal(){ for (int i = 0;i < n * 2; ++ i){ top[i] = i; sz[i] = 1; } for (int i = 1;i < n; ++ i){ int u = edge[i].u, v = edge[i].v, w = edge[i].w; if (find_top(u) == find_top(v)) continue; int nwp = n + i; nw[nwp] = w; sz[nwp] += sz[top[u]] + sz[top[v]]; fa[top[u]][0] = fa[top[v]][0] = nwp; top[top[u]] = top[top[v]] = nwp; } for (int i = 1;i < 20; ++ i) for (int j = 1;j < n * 2; ++ j) fa[j][i] = fa[fa[j][i - 1]][i - 1]; } inline void add(int u, int v, int w){ edge[++idx].u = u; edge[idx].v = v; edge[idx].w = w; } int main(){ scanf("%d%d", &n, &Q); for (int i = 1;i < n; ++ i){ int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u, v, w); } sort(edge + 1, edge + n); EK_kruskal(); while (Q --){ int k, v;scanf("%d%d", &k, &v); for (int i = 19;i >= 0; -- i) if (nw[fa[v][i]] >= k) v = fa[v][i]; printf("%d\n", (sz[v] - 1) >> 1); } return 0; } ```
by Ailuomangacencei @ 2023-11-11 19:19:07


@[Ailuomangacencei](/user/426187) 其实4年前的题解就有你这种做法了
by arrowpoint @ 2024-05-18 19:19:55


|