社区讨论
论#73毒瘤
P15089[UOI 2025 II Stage] OldPost --- NewPost参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mlnnh4g3
- 此快照首次捕获于
- 2026/02/15 19:16 3 周前
- 此快照最后确认于
- 2026/02/19 23:15 3 周前
改了好久了...#73一直UKE!
求dalao:
CPP#include <bits/stdc++.h>
using namespace std;
struct Tree
{
int n;
vector<int> head, to, nxt;
int ec;
Tree(int n_, int m) : n(n_), head(n_ + 1, -1), to(2 * m), nxt(2 * m), ec(0) {}
inline void addEdge(int u, int v)
{
to[ec] = v;
nxt[ec] = head[u];
head[u] = ec++;
}
};
static inline int bfs_farthest(const Tree &tr, int src, vector<int> &dist, vector<int> &par)
{
dist.assign(tr.n + 1, -1);
par.assign(tr.n + 1, -1);
queue<int> q;
q.push(src);
dist[src] = 0;
par[src] = -1;
int far = src;
while (!q.empty())
{
int u = q.front();
q.pop();
if (dist[u] > dist[far]) far = u;
for (int e = tr.head[u]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (dist[v] != -1) continue;
dist[v] = dist[u] + 1;
par[v] = u;
q.push(v);
}
}
return far;
}
struct RootedInfo
{
int n;
int root;
int K;
vector<int> parent;
vector<int> depth;
vector<int> order;
vector<int> cnt;
vector<int> rep;
};
static inline RootedInfo build_rooted_component(const Tree &tr, int root, int bannedParent, int K)
{
RootedInfo info;
info.n = tr.n;
info.root = root;
info.K = K;
info.parent.assign(tr.n + 1, -1);
info.depth.assign(tr.n + 1, -1);
info.cnt.assign(tr.n + 1, 0);
info.rep.assign(tr.n + 1, -1);
info.order.clear();
info.order.reserve(tr.n);
vector<int> st;
st.reserve(tr.n);
st.push_back(root);
info.parent[root] = bannedParent;
info.depth[root] = 0;
while (!st.empty())
{
int u = st.back();
st.pop_back();
info.order.push_back(u);
for (int e = tr.head[u]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (v == info.parent[u]) continue;
if (info.depth[v] != -1) continue;
info.parent[v] = u;
info.depth[v] = info.depth[u] + 1;
st.push_back(v);
}
}
for (int idx = (int)info.order.size() - 1; idx >= 0; --idx)
{
int u = info.order[idx];
if (info.depth[u] == K)
{
info.cnt[u] = 1;
info.rep[u] = u;
}
for (int e = tr.head[u]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (v == info.parent[u]) continue;
info.cnt[u] += info.cnt[v];
if (info.rep[u] == -1 && info.rep[v] != -1) info.rep[u] = info.rep[v];
}
}
return info;
}
struct TwoPick
{
int a;
int b;
int lcaDepth;
};
static inline TwoPick pick_two_best(const Tree &tr, const RootedInfo &info, int start)
{
if (info.cnt[start] <= 0)
return TwoPick{info.root, info.root, info.K};
if (info.cnt[start] == 1)
{
int x = info.rep[start];
return TwoPick{x, x, info.K};
}
int x = start;
while (true)
{
int c1 = -1, c2 = -1;
for (int e = tr.head[x]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (v == info.parent[x]) continue;
if (info.cnt[v] <= 0) continue;
if (c1 == -1) c1 = v;
else
{
c2 = v;
break;
}
}
if (c2 != -1)
{
return TwoPick{info.rep[c1], info.rep[c2], info.depth[x]};
}
for (int e = tr.head[x]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (v == info.parent[x]) continue;
if (info.cnt[v] > 0)
{
x = v;
break;
}
}
}
}
static inline vector<int> path_to_ancestor(int u, int anc, const vector<int> &parent)
{
vector<int> res;
while (u != -1)
{
res.push_back(u);
if (u == anc) break;
u = parent[u];
}
return res;
}
static inline vector<int> build_path_via_center(int a, int b, int center, const vector<int> &parent)
{
vector<int> left = path_to_ancestor(a, center, parent);
vector<int> right = path_to_ancestor(b, center, parent);
reverse(right.begin(), right.end());
for (int i = 1; i < (int)right.size(); ++i) left.push_back(right[i]);
return left;
}
static inline vector<int> build_path_via_edge(int a, int u, int v, int b,
const vector<int> &parU, const vector<int> &parV)
{
vector<int> left = path_to_ancestor(a, u, parU);
vector<int> right = path_to_ancestor(b, v, parV);
reverse(right.begin(), right.end());
vector<int> res;
res.reserve(left.size() + 1 + right.size());
for (int x : left) res.push_back(x);
res.push_back(v);
for (int i = 1; i < (int)right.size(); ++i) res.push_back(right[i]);
return res;
}
static inline void print_path(const vector<int> &p)
{
for (int i = 0; i < (int)p.size(); ++i)
{
cout << p[i] << (i + 1 == (int)p.size() ? '\n' : ' ');
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
Tree tr(n, n - 1);
for (int i = 0; i < n - 1; ++i)
{
int x, y;
cin >> x >> y;
tr.addEdge(x, y);
tr.addEdge(y, x);
}
vector<int> dist, par;
int s = bfs_farthest(tr, 1, dist, par);
int t = bfs_farthest(tr, s, dist, par);
vector<int> P;
for (int x = t; x != -1; x = par[x]) P.push_back(x);
reverse(P.begin(), P.end());
int D = (int)P.size() - 1;
int L = D + 1;
vector<int> pathA, pathB;
if (D % 2 == 0)
{
int c = P[D / 2];
int r = D / 2;
RootedInfo info = build_rooted_component(tr, c, -1, r);
vector<int> subs;
subs.reserve(8);
for (int e = tr.head[c]; e != -1; e = tr.nxt[e])
{
int v = tr.to[e];
if (info.cnt[v] > 0) subs.push_back(v);
}
if ((int)subs.size() >= 4)
{
int a1 = info.rep[subs[0]];
int a2 = info.rep[subs[1]];
int b1 = info.rep[subs[2]];
int b2 = info.rep[subs[3]];
pathA = build_path_via_center(a1, a2, c, info.parent);
pathB = build_path_via_center(b1, b2, c, info.parent);
}
else if ((int)subs.size() == 3)
{
int R = subs[0];
TwoPick bestR = pick_two_best(tr, info, R);
for (int i = 1; i < 3; ++i)
{
TwoPick cand = pick_two_best(tr, info, subs[i]);
if (cand.lcaDepth < bestR.lcaDepth)
{
bestR = cand;
R = subs[i];
}
}
int X = -1, Y = -1;
for (int u : subs)
{
if (u == R) continue;
if (X == -1) X = u;
else Y = u;
}
int endX = info.rep[X];
int endY = info.rep[Y];
pathA = build_path_via_center(bestR.a, endX, c, info.parent);
pathB = build_path_via_center(bestR.b, endY, c, info.parent);
}
else
{
int A = subs[0], B = subs[1];
TwoPick pA = pick_two_best(tr, info, A);
TwoPick pB = pick_two_best(tr, info, B);
pathA = build_path_via_center(pA.a, pB.a, c, info.parent);
pathB = build_path_via_center(pA.b, pB.b, c, info.parent);
}
}
else
{
int u = P[D / 2];
int v = P[D / 2 + 1];
int k = D / 2;
RootedInfo infoU = build_rooted_component(tr, u, v, k); // u-side, block v
RootedInfo infoV = build_rooted_component(tr, v, u, k); // v-side, block u
TwoPick pU = pick_two_best(tr, infoU, u);
TwoPick pV = pick_two_best(tr, infoV, v);
pathA = build_path_via_edge(pU.a, u, v, pV.a, infoU.parent, infoV.parent);
pathB = build_path_via_edge(pU.b, u, v, pV.b, infoU.parent, infoV.parent);
}
if ((int)pathA.size() != L) pathA = P;
if ((int)pathB.size() != L) pathB = P;
cout << L << "\n";
print_path(pathA);
print_path(pathB);
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...