結果
| 問題 | No.3405 Engineering University of Tree |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-12 00:24:47 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 565 ms / 2,000 ms |
| コード長 | 8,788 bytes |
| 記録 | |
| コンパイル時間 | 2,045 ms |
| コンパイル使用メモリ | 140,128 KB |
| 実行使用メモリ | 73,952 KB |
| 最終ジャッジ日時 | 2025-12-12 00:24:59 |
| 合計ジャッジ時間 | 12,265 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 21 |
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:250:12: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
250 | scanf("%d", &C[u]);
| ~~~~~^~~~~~~~~~~~~
main.cpp:253:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
253 | scanf("%d", &E[u][c]);
| ~~~~~^~~~~~~~~~~~~~~~
ソースコード
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <chrono>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
struct Hld {
int n, rt;
// needs to be tree
// vertex lists
// modified in build(rt) (parent removed, heavy child first)
vector<vector<int>> graph;
vector<int> sz, par, dep;
int zeit;
vector<int> dis, fin, sid;
// head vertex (minimum depth) in heavy path
vector<int> head;
Hld() : n(0), rt(-1), zeit(0) {}
explicit Hld(int n_) : n(n_), rt(-1), graph(n), zeit(0) {}
void ae(int u, int v) {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
graph[u].push_back(v);
graph[v].push_back(u);
}
void dfsSz(int u) {
sz[u] = 1;
for (const int v : graph[u]) {
auto it = std::find(graph[v].begin(), graph[v].end(), u);
if (it != graph[v].end()) graph[v].erase(it);
par[v] = u;
dep[v] = dep[u] + 1;
dfsSz(v);
sz[u] += sz[v];
}
}
void dfsHld(int u) {
dis[u] = zeit++;
const int deg = graph[u].size();
if (deg > 0) {
int vm = graph[u][0];
int jm = 0;
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
if (sz[vm] < sz[v]) {
vm = v;
jm = j;
}
}
swap(graph[u][0], graph[u][jm]);
head[vm] = head[u];
dfsHld(vm);
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
head[v] = v;
dfsHld(v);
}
}
fin[u] = zeit;
}
void build(int rt_) {
assert(0 <= rt_); assert(rt_ < n);
rt = rt_;
sz.assign(n, 0);
par.assign(n, -1);
dep.assign(n, -1);
dep[rt] = 0;
dfsSz(rt);
zeit = 0;
dis.assign(n, -1);
fin.assign(n, -1);
head.assign(n, -1);
head[rt] = rt;
dfsHld(rt);
assert(zeit == n);
sid.assign(n, -1);
for (int u = 0; u < n; ++u) sid[dis[u]] = u;
}
friend ostream &operator<<(ostream &os, const Hld &hld) {
const int maxDep = *max_element(hld.dep.begin(), hld.dep.end());
vector<string> ss(2 * maxDep + 1);
int pos = 0, maxPos = 0;
for (int j = 0; j < hld.n; ++j) {
const int u = hld.sid[j];
const int d = hld.dep[u];
if (hld.head[u] == u) {
if (j != 0) {
pos = maxPos + 1;
ss[2 * d - 1].resize(pos, '-');
ss[2 * d - 1] += '+';
}
} else {
ss[2 * d - 1].resize(pos, ' ');
ss[2 * d - 1] += '|';
}
ss[2 * d].resize(pos, ' ');
ss[2 * d] += std::to_string(u);
if (maxPos < static_cast<int>(ss[2 * d].size())) {
maxPos = ss[2 * d].size();
}
}
for (int d = 0; d <= 2 * maxDep; ++d) os << ss[d] << '\n';
return os;
}
bool contains(int u, int v) const {
return (dis[u] <= dis[v] && dis[v] < fin[u]);
}
int lca(int u, int v) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
for (; head[u] != head[v]; ) (dis[u] > dis[v]) ? (u = par[head[u]]) : (v = par[head[v]]);
return (dis[u] > dis[v]) ? v : u;
}
int jumpUp(int u, int d) const {
assert(0 <= u); assert(u < n);
assert(d >= 0);
if (dep[u] < d) return -1;
const int tar = dep[u] - d;
for (u = head[u]; ; u = head[par[u]]) {
if (dep[u] <= tar) return sid[dis[u] + (tar - dep[u])];
}
}
int jump(int u, int v, int d) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
assert(d >= 0);
const int l = lca(u, v);
const int du = dep[u] - dep[l], dv = dep[v] - dep[l];
if (d <= du) {
return jumpUp(u, d);
} else if (d <= du + dv) {
return jumpUp(v, du + dv - d);
} else {
return -1;
}
}
// [u, v) or [u, v]
template <class F> void doPathUp(int u, int v, bool inclusive, F f) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
assert(contains(v, u));
for (; head[u] != head[v]; u = par[head[u]]) f(dis[head[u]], dis[u] + 1);
if (inclusive) {
f(dis[v], dis[u] + 1);
} else {
if (v != u) f(dis[v] + 1, dis[u] + 1);
}
}
// not path order, include lca(u, v) or not
template <class F> void doPath(int u, int v, bool inclusive, F f) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
const int l = lca(u, v);
doPathUp(u, l, false, f);
doPathUp(v, l, inclusive, f);
}
// find deepest true for pred: [u, root] -> bool, increasing
// -1 if !pred(rt)
template <class Pred> int findUp(int u, Pred pred) const {
assert(0 <= u); assert(u < n);
for (; ~u; ) {
const int h = head[u];
if (pred(h)) {
int lo = dis[h], hi = dis[u] + 1;
for (; lo + 1 < hi; ) {
const int mid = (lo + hi) / 2;
(pred(sid[mid]) ? lo : hi) = mid;
}
return sid[lo];
}
u = par[h];
}
return -1;
}
// (vs, ps): compressed tree
// vs: DFS order (sorted by dis)
// vs[ps[x]]: the parent of vs[x]
// ids[vs[x]] = x, not set for non-tree vertex
vector<int> ids;
pair<vector<int>, vector<int>> compress(vector<int> us) {
// O(n) first time
ids.resize(n, -1);
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
int usLen = us.size();
assert(usLen >= 1);
for (int x = 1; x < usLen; ++x) us.push_back(lca(us[x - 1], us[x]));
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
usLen = us.size();
for (int x = 0; x < usLen; ++x) ids[us[x]] = x;
vector<int> ps(usLen, -1);
for (int x = 1; x < usLen; ++x) ps[x] = ids[lca(us[x - 1], us[x])];
return make_pair(us, ps);
}
};
////////////////////////////////////////////////////////////////////////////////
int N;
vector<int> C;
vector<vector<int>> E;
int main() {
for (; ~scanf("%d", &N); ) {
C.resize(N);
E.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%d", &C[u]);
E[u].resize(C[u]);
for (int c = 0; c < C[u]; ++c) {
scanf("%d", &E[u][c]);
--E[u][c];
}
}
vector<vector<int>> edges(N);
for (int u = 0; u < N; ++u) {
for (const int i : E[u]) {
edges[i].push_back(u);
}
}
Hld hld(N);
for (int i = 0; i < N - 1; ++i) {
hld.ae(edges[i][0], edges[i][1]);
}
hld.build(0);
// cerr<<hld<<flush;
vector<pair<int, int>> cus;
for (int u = 1; u < N; ++u) cus.emplace_back(C[u], u);
sort(cus.begin(), cus.end(), greater<pair<int, int>>{});
vector<int> ans(N, 0);
for (int k = 1; k < N; ++k) {
vector<int> us{0};
for (int j = 0; j < (int)cus.size() && cus[j].first >= k; ++j) us.push_back(cus[j].second);
const auto vsps = hld.compress(us);
const auto &vs = vsps.first;
const auto &ps = vsps.second;
const int n = vs.size();
vector<int> fs(n, 0);
for (int y = n; --y >= 0; ) {
const int v = vs[y];
const int deg = C[v] - (v ? 1 : 0);
if (deg - fs[y] >= k) {
// cerr<<"k = "<<k<<" use0 "<<vs[y]<<"; deg = "<<deg<<", fs[y] = "<<fs[y]<<endl;
++ans[k];
} else if (deg - fs[y] == k - 1) {
const int x = ps[y];
if (~x) {
// cerr<<"k = "<<k<<" use1 "<<vs[y]<<"; deg = "<<deg<<", fs[y] = "<<fs[y]<<endl;
++ans[k];
if (hld.dep[vs[y]] - hld.dep[vs[x]] == 1) ++fs[x];
}
}
}
}
for (int k = 1; k < N; ++k) {
if (k > 1) printf(" ");
printf("%d", ans[k]);
}
puts("");
}
return 0;
}