QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#538428 | #8941. Even or Odd Spanning Tree | ucup-team133# | WA | 141ms | 3628kb | C++23 | 16.1kb | 2024-08-31 11:48:55 | 2024-08-31 11:48:55 |
Judging History
answer
#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...) void(0)
#endif
template <class T> std::istream& operator>>(std::istream& is, std::vector<T>& v) {
for (auto& e : v) {
is >> e;
}
return is;
}
template <class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
for (std::string_view sep = ""; const auto& e : v) {
os << std::exchange(sep, " ") << e;
}
return os;
}
template <class T, class U = T> bool chmin(T& x, U&& y) {
return y < x and (x = std::forward<U>(y), true);
}
template <class T, class U = T> bool chmax(T& x, U&& y) {
return x < y and (x = std::forward<U>(y), true);
}
template <class T> void mkuni(std::vector<T>& v) {
std::ranges::sort(v);
auto result = std::ranges::unique(v);
v.erase(result.begin(), result.end());
}
template <class T> int lwb(const std::vector<T>& v, const T& x) {
return std::distance(v.begin(), std::ranges::lower_bound(v, x));
}
namespace atcoder {
// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
public:
dsu() : _n(0) {}
explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}
int merge(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
return x;
}
bool same(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
return leader(a) == leader(b);
}
int leader(int a) {
assert(0 <= a && a < _n);
if (parent_or_size[a] < 0) return a;
return parent_or_size[a] = leader(parent_or_size[a]);
}
int size(int a) {
assert(0 <= a && a < _n);
return -parent_or_size[leader(a)];
}
std::vector<std::vector<int>> groups() {
std::vector<int> leader_buf(_n), group_size(_n);
for (int i = 0; i < _n; i++) {
leader_buf[i] = leader(i);
group_size[leader_buf[i]]++;
}
std::vector<std::vector<int>> result(_n);
for (int i = 0; i < _n; i++) {
result[i].reserve(group_size[i]);
}
for (int i = 0; i < _n; i++) {
result[leader_buf[i]].push_back(i);
}
result.erase(
std::remove_if(result.begin(), result.end(),
[&](const std::vector<int>& v) { return v.empty(); }),
result.end());
return result;
}
private:
int _n;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
};
} // namespace atcoder
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
namespace internal {
// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (unsigned int)(n)) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
int x = 0;
while (!(n & (1 << x))) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
unsigned long index;
_BitScanForward(&index, n);
return index;
#else
return __builtin_ctz(n);
#endif
}
} // namespace internal
} // namespace atcoder
namespace atcoder {
template <class S,
S (*op)(S, S),
S (*e)(),
class F,
S (*mapping)(F, S),
F (*composition)(F, F),
F (*id)()>
struct lazy_segtree {
public:
lazy_segtree() : lazy_segtree(0) {}
explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
log = internal::ceil_pow2(_n);
size = 1 << log;
d = std::vector<S>(2 * size, e());
lz = std::vector<F>(size, id());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
return d[p];
}
S prod(int l, int r) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return e();
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
S sml = e(), smr = e();
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() { return d[1]; }
void apply(int p, F f) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
d[p] = mapping(f, d[p]);
for (int i = 1; i <= log; i++) update(p >> i);
}
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return;
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
{
int l2 = l, r2 = r;
while (l < r) {
if (l & 1) all_apply(l++, f);
if (r & 1) all_apply(--r, f);
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
}
for (int i = 1; i <= log; i++) {
if (((l >> i) << i) != l) update(l >> i);
if (((r >> i) << i) != r) update((r - 1) >> i);
}
}
template <bool (*g)(S)> int max_right(int l) {
return max_right(l, [](S x) { return g(x); });
}
template <class G> int max_right(int l, G g) {
assert(0 <= l && l <= _n);
assert(g(e()));
if (l == _n) return _n;
l += size;
for (int i = log; i >= 1; i--) push(l >> i);
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!g(op(sm, d[l]))) {
while (l < size) {
push(l);
l = (2 * l);
if (g(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*g)(S)> int min_left(int r) {
return min_left(r, [](S x) { return g(x); });
}
template <class G> int min_left(int r, G g) {
assert(0 <= r && r <= _n);
assert(g(e()));
if (r == 0) return 0;
r += size;
for (int i = log; i >= 1; i--) push((r - 1) >> i);
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!g(op(d[r], sm))) {
while (r < size) {
push(r);
r = (2 * r + 1);
if (g(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
private:
int _n, size, log;
std::vector<S> d;
std::vector<F> lz;
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
void all_apply(int k, F f) {
d[k] = mapping(f, d[k]);
if (k < size) lz[k] = composition(f, lz[k]);
}
void push(int k) {
all_apply(2 * k, lz[k]);
all_apply(2 * k + 1, lz[k]);
lz[k] = id();
}
};
} // namespace atcoder
struct HeavyLightDecomposition {
std::vector<std::vector<int>> G; // child of vertex v on heavy edge is G[v].front() if it is not parent of v
int n, time;
std::vector<int> par, // parent of vertex v
sub, // size of subtree whose root is v
dep, // distance bitween root and vertex v
head, // vertex that is the nearest to root on heavy path of vertex v
tree_id, // id of tree vertex v belongs to
vertex_id, // id of vertex v (consecutive on heavy paths)
vertex_id_inv; // vertex_id_inv[vertex_id[v]] = v
HeavyLightDecomposition() {}
HeavyLightDecomposition(int n)
: G(n),
n(n),
time(0),
par(n, -1),
sub(n),
dep(n, 0),
head(n),
tree_id(n, -1),
vertex_id(n, -1),
vertex_id_inv(n) {}
void add_edge(int u, int v) {
assert(0 <= u and u < n);
assert(0 <= v and v < n);
G[u].emplace_back(v);
G[v].emplace_back(u);
}
void build(std::vector<int> roots = {0}) {
int tree_id_cur = 0;
for (int& r : roots) {
assert(0 <= r and r < n);
dfs_sz(r);
head[r] = r;
dfs_hld(r, tree_id_cur++);
}
assert(time == n);
for (int v = 0; v < n; v++) vertex_id_inv[vertex_id[v]] = v;
}
int idx(int v) const { return vertex_id[v]; }
int la(int v, int k) const {
assert(0 <= v and v < n);
assert(0 <= k and k <= dep[v]);
while (1) {
int u = head[v];
if (vertex_id[v] - k >= vertex_id[u]) return vertex_id_inv[vertex_id[v] - k];
k -= vertex_id[v] - vertex_id[u] + 1;
v = par[u];
}
}
int lca(int u, int v) const {
assert(0 <= u and u < n);
assert(0 <= v and v < n);
assert(tree_id[u] == tree_id[v]);
for (;; v = par[head[v]]) {
if (vertex_id[u] > vertex_id[v]) std::swap(u, v);
if (head[u] == head[v]) return u;
}
}
int jump(int s, int t, int i) const {
assert(0 <= s and s < n);
assert(0 <= t and t < n);
assert(0 <= i);
if (tree_id[s] != tree_id[t]) return -1;
if (i == 0) return s;
int p = lca(s, t), d = dep[s] + dep[t] - 2 * dep[p];
if (d < i) return -1;
if (dep[s] - dep[p] >= i) return la(s, i);
return la(t, d - i);
}
int distance(int u, int v) const {
assert(0 <= u and u < n);
assert(0 <= v and v < n);
assert(tree_id[u] == tree_id[v]);
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
template <typename F> void query_path(int u, int v, const F& f, bool vertex = false) const {
assert(0 <= u and u < n);
assert(0 <= v and v < n);
assert(tree_id[u] == tree_id[v]);
int p = lca(u, v);
for (auto& e : ascend(u, p)) f(e.second, e.first + 1);
if (vertex) f(vertex_id[p], vertex_id[p] + 1);
for (auto& e : descend(p, v)) f(e.first, e.second + 1);
}
template <typename F> void query_path_noncommutative(int u, int v, const F& f, bool vertex = false) const {
assert(0 <= u and u < n);
assert(0 <= v and v < n);
assert(tree_id[u] == tree_id[v]);
int p = lca(u, v);
for (auto& e : ascend(u, p)) f(e.first + 1, e.second);
if (vertex) f(vertex_id[p], vertex_id[p] + 1);
for (auto& e : descend(p, v)) f(e.first, e.second + 1);
}
template <typename F> void query_subtree(int u, const F& f, bool vertex = false) const {
assert(0 <= u and u < n);
f(vertex_id[u] + !vertex, vertex_id[u] + sub[u]);
}
std::pair<std::unordered_map<int, std::vector<int>>, int> auxiliary_tree(std::vector<int> vs) {
int len = vs.size();
std::sort(vs.begin(), vs.end(), [&](int i, int j) { return vertex_id[i] < vertex_id[j]; });
for (int i = 0; i + 1 < len; i++) vs.emplace_back(lca(vs[i], vs[i + 1]));
std::sort(vs.begin(), vs.end(), [&](int i, int j) { return vertex_id[i] < vertex_id[j]; });
vs.erase(std::unique(vs.begin(), vs.end()), vs.end());
std::vector<int> st;
std::unordered_map<int, std::vector<int>> res;
for (int v : vs) {
while (not st.empty() and vertex_id[st.back()] + sub[st.back()] <= vertex_id[v]) st.pop_back();
if (not st.empty()) res[st.back()].emplace_back(v);
st.emplace_back(v);
}
return {res, vs[0]};
}
private:
void dfs_sz(int v) {
sub[v] = 1;
if (!G[v].empty() and G[v].front() == par[v]) std::swap(G[v].front(), G[v].back());
for (int& u : G[v]) {
if (u == par[v]) continue;
par[u] = v;
dep[u] = dep[v] + 1;
dfs_sz(u);
sub[v] += sub[u];
if (sub[u] > sub[G[v].front()]) std::swap(u, G[v].front());
}
}
void dfs_hld(int v, int tree_id_cur) {
vertex_id[v] = time++;
tree_id[v] = tree_id_cur;
for (int& u : G[v]) {
if (u == par[v]) continue;
head[u] = (u == G[v][0] ? head[v] : u);
dfs_hld(u, tree_id_cur);
}
}
std::vector<std::pair<int, int>> ascend(int u, int v) const { // [u, v), v is ancestor of u
std::vector<std::pair<int, int>> res;
while (head[u] != head[v]) {
res.emplace_back(vertex_id[u], vertex_id[head[u]]);
u = par[head[u]];
}
if (u != v) res.emplace_back(vertex_id[u], vertex_id[v] + 1);
return res;
}
std::vector<std::pair<int, int>> descend(int u, int v) const { // (u, v], u is ancestor of v
if (u == v) return {};
if (head[u] == head[v]) return {{vertex_id[u] + 1, vertex_id[v]}};
auto res = descend(u, par[head[v]]);
res.emplace_back(vertex_id[head[v]], vertex_id[v]);
return res;
}
};
using ll = long long;
using namespace std;
struct S {
array<int, 2> maxi;
};
S op(S l, S r) { return S{{max(l.maxi[0], r.maxi[0]), max(l.maxi[1], r.maxi[1])}}; }
S e() { return S{{0, 0}}; }
S mapping(S l, S r) { return op(l, r); }
S composition(S l, S r) { return op(l, r); }
S id() { return e(); }
void solve() {
int n, m;
cin >> n >> m;
vector<int> u(m), v(m), w(m);
for (int i = 0; i < m; i++) {
cin >> u[i] >> v[i] >> w[i];
u[i]--, v[i]--;
}
vector<int> ord(m);
iota(ord.begin(), ord.end(), 0);
ranges::sort(ord, {}, [&](int i) { return w[i]; });
atcoder::dsu dsu(n);
vector<bool> used(m, false);
ll min_span = 0;
HeavyLightDecomposition G(n);
for (int i : ord) {
if (dsu.same(u[i], v[i])) continue;
dsu.merge(u[i], v[i]);
G.add_edge(u[i], v[i]);
min_span += w[i];
used[i] = true;
}
if (dsu.size(0) < n) {
cout << -1 << " " << -1 << "\n";
return;
}
G.build();
vector<ll> ans(2, -1);
ans[min_span & 1] = min_span;
vector<S> init(n, e());
for (int i = 0; i < m; i++) {
if (not used[i]) continue;
if (G.dep[u[i]] > G.dep[v[i]]) swap(u[i], v[i]); // v[i] is child of u[i]
S val = e();
val.maxi[w[i] & 1] = w[i];
init[G.idx(v[i])] = val;
}
atcoder::lazy_segtree<S, op, e, S, mapping, composition, id> seg(init);
ll other = -1;
for (int i = 0; i < m; i++) {
if (used[i]) continue;
int parity = w[i] & 1;
auto res = e();
auto q = [&](int l, int r) { res = op(res, seg.prod(l, r)); };
G.query_path(u[i], v[i], q);
if (res.maxi[parity ^ 1] != 0) chmax(other, min_span - res.maxi[parity ^ 1] + w[i]);
}
ans[(min_span & 1) ^ 1] = other;
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
int T;
cin >> T;
for (; T--;) solve();
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 0ms
memory: 3628kb
input:
3 2 1 1 2 5 3 1 1 3 1 4 4 1 2 1 1 3 1 1 4 1 2 4 2
output:
-1 5 -1 -1 4 3
result:
ok 6 numbers
Test #2:
score: -100
Wrong Answer
time: 141ms
memory: 3592kb
input:
10000 16 50 1 2 649251632 2 3 605963017 3 4 897721528 4 5 82446151 5 6 917109168 6 7 79647183 7 8 278566178 7 9 573504723 3 10 679859251 8 11 563113083 1 12 843328546 10 13 594049160 11 14 997882839 7 15 569431750 2 16 244494799 16 7 960172373 13 4 317888322 13 3 446883598 9 3 678142319 5 8 43208692...
output:
3140067932 3941554631 1262790434 2124445815 1263932600 2177809565 2128472300 1180186165 2248358640 3162318131 4696867870 3738936375 2011213264 1058677117 4144333014 3402127725 2081445350 1187873655 1395482806 2324672773 3456885934 4302070719 3943951826 4702420591 2479987500 3216859457 2909126794 388...
result:
wrong answer 2nd numbers differ - expected: '3159441841', found: '3941554631'