結果
| 問題 | No.3405 Engineering University of Tree |
| コンテスト | |
| ユーザー |
とりゐ
|
| 提出日時 | 2025-12-12 14:37:37 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 872 ms / 2,000 ms |
| コード長 | 6,056 bytes |
| 記録 | |
| コンパイル時間 | 3,997 ms |
| コンパイル使用メモリ | 313,820 KB |
| 実行使用メモリ | 123,856 KB |
| 最終ジャッジ日時 | 2025-12-12 14:38:00 |
| 合計ジャッジ時間 | 16,509 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 21 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define elif else if
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define pii pair<int, int>
#define repname(a, b, c, d, e, ...) e
#define rep(...) repname(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define rep0(x) for (int rep_counter = 0; rep_counter < (x); ++rep_counter)
#define rep1(i, x) for (int i = 0; i < (x); ++i)
#define rep2(i, l, r) for (int i = (l); i < (r); ++i)
#define rep3(i, l, r, c) for (int i = (l); i < (r); i += (c))
template <typename T>
ostream &operator<<(ostream &os, const set<T> s)
{
os << "{";
bool first = true;
for (const auto &x : s)
{
if (!first)
os << ", ";
os << x;
first = false;
}
os << "}";
return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> s)
{
os << "{";
bool first = true;
for (const auto &x : s)
{
if (!first)
os << ", ";
os << x;
first = false;
}
os << "}";
return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const map<K, V> m)
{
os << "{";
bool first = true;
for (const auto &[key, value] : m)
{
if (!first)
os << ", ";
os << key << ": " << value;
first = false;
}
os << "}";
return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const unordered_map<K, V> m)
{
os << "{";
bool first = true;
for (const auto &[key, value] : m)
{
if (!first)
os << ", ";
os << key << ": " << value;
first = false;
}
os << "}";
return os;
}
template <typename T, size_t N>
ostream &operator<<(ostream &os, const array<T, N> a)
{
os << "(";
for (size_t i = 0; i < N; ++i)
{
if (i > 0)
os << ", ";
os << a[i];
}
os << ")";
return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> p)
{
os << "(" << p.first << ", " << p.second << ")";
return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> v)
{
os << "[";
for (int i = 0; i < v.size(); ++i)
{
if (i > 0)
os << ", ";
os << v[i];
}
os << "]";
return os;
}
template <class T>
void print(T x)
{
cout << x << '\n';
}
template <class Head, class... Tail>
void print(Head &&head, Tail &&...tail)
{
cout << head << ' ';
print(forward<Tail>(tail)...);
}
// -----------------------------------------------
struct LCA
{
int n;
vvi G, st;
vi dep, S, FS;
int LOG(int i) { return 31 - __builtin_clz(i); }
LCA(int n, vvi &G, int root) : n(n), G(G), dep(n, -1), FS(n)
{
dep[root] = 0;
dfs(root, -1);
int L = S.size();
st.resize(LOG(L) + 1);
st[0] = S;
int b = 1;
rep(i, LOG(L))
{
int sz = st[i].size() - b;
st[i + 1].resize(sz);
rep(j, sz)
{
int u = st[i][j];
int v = st[i][j + b];
st[i + 1][j] = (dep[u] <= dep[v]) ? u : v;
}
b *= 2;
}
}
void dfs(int v, int p)
{
FS[v] = S.size();
S.push_back(v);
for (auto u : G[v])
{
if (u != p)
{
dep[u] = dep[v] + 1;
dfs(u, v);
S.push_back(v);
}
}
}
int lca(int u, int v)
{
int x = FS[u], y = FS[v];
if (x > y)
swap(x, y);
int l = LOG(y - x + 1);
int px = st[l][x], py = st[l][y - (1 << l) + 1];
return (dep[px] <= dep[py]) ? px : py;
}
};
/*
- `AuxiliaryTree T(n, edge, 0);` で初期化
- 頂点列 `vector<int> vs` に対して `int r = T.query(vs);`
で補助的な木の根が返る.`vector<int> T.G[v]`
にその補助的な木に含まれる頂点の子が格納されている.
*/
struct AuxiliaryTree
{
int n, dum;
vi L, R, last, par; // L, R: eular tour 上で頂点 v が登場する最初/最後の位置
vvi edge, G;
LCA lca;
AuxiliaryTree(int n, vvi edge, int root)
: n(n), edge(edge), G(n), lca(n, edge, root), L(n, 0), R(n, 0), last(n, -1), par(n, -1)
{
dum = 0;
dfs(0, -1);
};
void dfs(int v, int p)
{
par[v] = p;
L[v] = dum;
dum++;
for (auto u : edge[v])
if (u != p)
dfs(u, v);
R[v] = dum;
dum++;
}
int query(vi vs)
{
assert(vs.size() != 0);
sort(vs.begin(), vs.end(), [&](int u, int v)
{ return L[u] < L[v]; }); // pre-order で sort
int sz = vs.size();
rep(i, sz - 1) vs.push_back(lca.lca(vs[i], vs[i + 1]));
sort(vs.begin(), vs.end(), [&](int u, int v)
{ return L[u] < L[v]; }); // pre-order で sort
vi stc;
int prv = -1;
for (auto v : vs)
{
if (prv == v)
continue;
prv = v;
while (!stc.empty() && R[stc.back()] < L[v])
stc.pop_back();
if (!stc.empty())
G[stc.back()].push_back(v);
G[v].clear();
stc.push_back(v);
}
return stc[0];
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(20);
int n;
cin >> n;
vvi G(n);
vvi E(n - 1);
rep(v, n)
{
int c;
cin >> c;
rep(c)
{
int e;
cin >> e;
e--;
E[e].push_back(v);
}
}
rep(e, n - 1)
{
int u = E[e][0], v = E[e][1];
G[u].push_back(v);
G[v].push_back(u);
}
AuxiliaryTree AT(n, G, 0);
vi par = AT.par;
vector<pair<int, int>> deg;
rep(i, n)
{
deg.push_back({G[i].size(), i});
}
sort(deg.rbegin(), deg.rend());
rep(q, 1, n)
{
vi vs;
for (auto [d, v] : deg)
{
if (d >= q)
vs.push_back(v);
else
break;
}
if (vs.size() == 0)
{
cout << "0" << " \n"[q + 1 == n];
continue;
}
int r = AT.query(vs);
unordered_map<int, int> mp;
int ans = 0;
auto dfs = [&](auto dfs, int v) -> void
{
for (auto u : AT.G[v])
{
dfs(dfs, u);
}
int x = (int)G[v].size() - mp[v];
if (x >= q)
{
ans++;
if (v != 0 && x == q)
{
mp[par[v]]++;
}
}
};
dfs(dfs, r);
cout << ans << " \n"[q + 1 == n];
}
}
とりゐ