Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions library/trees/uncommon/contour_range_query.hpp

This file was deleted.

59 changes: 0 additions & 59 deletions library/trees/uncommon/contour_range_update.hpp

This file was deleted.

29 changes: 0 additions & 29 deletions library/trees/uncommon/count_paths_per_length.hpp

This file was deleted.

43 changes: 0 additions & 43 deletions library/trees/uncommon/count_paths_per_node.hpp

This file was deleted.

37 changes: 0 additions & 37 deletions library/trees/uncommon/sum_adjacent.hpp

This file was deleted.

2 changes: 1 addition & 1 deletion tests/library_checker_aizu_tests/cd_asserts.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include "../../library/trees/uncommon/centroid_decomp.hpp"
#include "../../library/trees/centroid_decomp.hpp"
void cd_asserts(const vector<vector<int>>& adj) {
vector<int> decomp_size(sz(adj), -1);
vector<int> naive_par_decomp(sz(adj), -1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,51 @@
"https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include "../template.hpp"
#include "../../../library/contest/random.hpp"
#include "../../../library/trees/uncommon/count_paths_per_node.hpp"
#include "../../../library/trees/lca_rmq.hpp"
#include "../../../library/trees/uncommon/count_paths_per_length.hpp"
#include "../cd_asserts.hpp"
#include "../../../kactl/content/numerical/FastFourierTransform.h"
#include "../../../library/trees/edge_cd.hpp"
//! @param adj unrooted, connected forest
//! @param k number of edges
//! @returns array `num_paths` where `num_paths[i]` =
//! number of paths with k edges where node `i` is on the
//! path. 0-based nodes.
//! @time O(n log n)
//! @space this function allocates/returns various vectors
//! which are all O(n)
vector<ll> count_paths_per_node(const vector<vi>& adj,
int k) {
vector<ll> num_paths(sz(adj));
centroid(adj,
[&](const vector<vi>& cd_adj, int cent, int) {
vector pre_d{1}, cur_d{0};
auto dfs = [&](auto&& self, int u, int p,
int d) -> ll {
if (d > k) return 0LL;
if (sz(cur_d) <= d) cur_d.push_back(0);
cur_d[d]++;
ll cnt = 0;
if (k - d < sz(pre_d)) cnt += pre_d[k - d];
for (int c : cd_adj[u])
if (c != p) cnt += self(self, c, u, d + 1);
num_paths[u] += cnt;
return cnt;
};
auto dfs_child = [&](int child) -> ll {
ll cnt = dfs(dfs, child, cent, 1);
pre_d.resize(sz(cur_d));
for (int i = 1; i < sz(cur_d) && cur_d[i]; i++)
pre_d[i] += cur_d[i], cur_d[i] = 0;
return cnt;
};
for (int child : cd_adj[cent])
num_paths[cent] += dfs_child(child);
pre_d = cur_d = {0};
for (int child : cd_adj[cent] | views::reverse)
dfs_child(child);
});
return num_paths;
}
vector<vector<ll>> naive(const vector<vi>& adj) {
LCA lc(adj);
int n = sz(adj);
Expand All @@ -21,6 +62,32 @@ vector<vector<ll>> naive(const vector<vi>& adj) {
}
return cnts_naive;
}
//! @param adj unrooted, connected tree
//! @returns array `num_paths` where `num_paths[i]` = # of
//! paths in tree with `i` edges. `num_paths[1]` = # edges
//! @time O(n * logφ(n) * log2(n))
//! @space this function allocates/returns various vectors
//! which are each O(n)
vector<ll> count_paths_per_length(const vector<vi>& adj) {
vector<ll> num_paths(sz(adj));
if (sz(adj) >= 2) num_paths[1] = sz(adj) - 1;
edge_cd(adj,
[&](const vector<vi>& cd_adj, int cent, int split) {
vector<vector<double>> cnt(2, vector<double>(1));
auto dfs = [&](auto&& self, int u, int p, int d,
int side) -> void {
if (sz(cnt[side]) == d) cnt[side].push_back(0.0);
cnt[side][d]++;
for (int c : cd_adj[u])
if (c != p) self(self, c, u, 1 + d, side);
};
rep(i, 0, sz(cd_adj[cent]))
dfs(dfs, cd_adj[cent][i], cent, 1, i < split);
vector<double> prod = conv(cnt[0], cnt[1]);
rep(i, 0, sz(prod)) num_paths[i] += llround(prod[i]);
});
return num_paths;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
for (int n = 1; n <= 100; n++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
#define PROBLEM \
"https://judge.yosupo.jp/problem/frequency_table_of_tree_distance"
#include "../template.hpp"
#include "../../../library/trees/uncommon/count_paths_per_length.hpp"
#include "../../../kactl/content/numerical/FastFourierTransform.h"
#include "../../../library/trees/edge_cd.hpp"
//! @param adj unrooted, connected tree
//! @returns array `num_paths` where `num_paths[i]` = # of
//! paths in tree with `i` edges. `num_paths[1]` = # edges
//! @time O(n * logφ(n) * log2(n))
//! @space this function allocates/returns various vectors
//! which are each O(n)
vector<ll> count_paths_per_length(const vector<vi>& adj) {
vector<ll> num_paths(sz(adj));
if (sz(adj) >= 2) num_paths[1] = sz(adj) - 1;
edge_cd(adj,
[&](const vector<vi>& cd_adj, int cent, int split) {
vector<vector<double>> cnt(2, vector<double>(1));
auto dfs = [&](auto&& self, int u, int p, int d,
int side) -> void {
if (sz(cnt[side]) == d) cnt[side].push_back(0.0);
cnt[side][d]++;
for (int c : cd_adj[u])
if (c != p) self(self, c, u, 1 + d, side);
};
rep(i, 0, sz(cd_adj[cent]))
dfs(dfs, cd_adj[cent][i], cent, 1, i < split);
vector<double> prod = conv(cnt[0], cnt[1]);
rep(i, 0, sz(prod)) num_paths[i] += llround(prod[i]);
});
return num_paths;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
int n;
Expand Down
Loading
Loading