Submission #74140206
Source Code Expand
#ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
// disable assert
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }
#include <utility>
#include <cassert>
namespace nachia{
// ax + by = gcd(a,b)
// return ( x, - )
std::pair<long long, long long> ExtGcd(long long a, long long b){
long long x = 1, y = 0;
while(b){
long long u = a / b;
std::swap(a-=b*u, b);
std::swap(x-=y*u, y);
}
return std::make_pair(x, a);
}
} // namespace nachia
namespace nachia{
template<unsigned int MOD>
struct StaticModint{
private:
using u64 = unsigned long long;
unsigned int x;
public:
using my_type = StaticModint;
template< class Elem >
static Elem safe_mod(Elem x){
if(x < 0){
if(0 <= x+MOD) return x + MOD;
return MOD - ((-(x+MOD)-1) % MOD + 1);
}
return x % MOD;
}
StaticModint() : x(0){}
StaticModint(const my_type& a) : x(a.x){}
StaticModint& operator=(const my_type&) = default;
template< class Elem >
StaticModint(Elem v) : x(safe_mod(v)){}
unsigned int operator*() const { return x; }
my_type& operator+=(const my_type& r) { auto t = x + r.x; if(t >= MOD) t -= MOD; x = t; return *this; }
my_type operator+(const my_type& r) const { my_type res = *this; return res += r; }
my_type& operator-=(const my_type& r) { auto t = x + MOD - r.x; if(t >= MOD) t -= MOD; x = t; return *this; }
my_type operator-(const my_type& r) const { my_type res = *this; return res -= r; }
my_type operator-() const noexcept { my_type res = *this; res.x = ((res.x == 0) ? 0 : (MOD - res.x)); return res; }
my_type& operator*=(const my_type& r){ x = (u64)x * r.x % MOD; return *this; }
my_type operator*(const my_type& r) const { my_type res = *this; return res *= r; }
bool operator==(const my_type& r) const { return x == r.x; }
my_type pow(unsigned long long i) const {
my_type a = *this, res = 1;
while(i){ if(i & 1){ res *= a; } a *= a; i >>= 1; }
return res;
}
my_type inv() const { return my_type(ExtGcd(x, MOD).first); }
unsigned int val() const { return x; }
int hval() const { return int(x > MOD/2 ? x - MOD : x); }
static constexpr unsigned int mod() { return MOD; }
static my_type raw(unsigned int val) { auto res = my_type(); res.x = val; return res; }
my_type& operator/=(const my_type& r){ return operator*=(r.inv()); }
my_type operator/(const my_type& r) const { return operator*(r.inv()); }
};
} // namespace nachia
using Mint = nachia::StaticModint<998244353>;
namespace nachia{
template<class Elem>
class CsrArray{
public:
struct ListRange{
using iterator = typename std::vector<Elem>::iterator;
iterator begi, endi;
iterator begin() const { return begi; }
iterator end() const { return endi; }
int size() const { return (int)std::distance(begi, endi); }
Elem& operator[](int i) const { return begi[i]; }
};
struct ConstListRange{
using iterator = typename std::vector<Elem>::const_iterator;
iterator begi, endi;
iterator begin() const { return begi; }
iterator end() const { return endi; }
int size() const { return (int)std::distance(begi, endi); }
const Elem& operator[](int i) const { return begi[i]; }
};
private:
int m_n;
std::vector<Elem> m_list;
std::vector<int> m_pos;
public:
CsrArray() : m_n(0), m_list(), m_pos() {}
static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
CsrArray res;
res.m_n = n;
std::vector<int> buf(n+1, 0);
for(auto& [u,v] : items){ ++buf[u]; }
for(int i=1; i<=n; i++) buf[i] += buf[i-1];
res.m_list.resize(buf[n]);
for(int i=(int)items.size()-1; i>=0; i--){
res.m_list[--buf[items[i].first]] = std::move(items[i].second);
}
res.m_pos = std::move(buf);
return res;
}
static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
CsrArray res;
res.m_n = pos.size() - 1;
res.m_list = std::move(list);
res.m_pos = std::move(pos);
return res;
}
ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
int size() const { return m_n; }
int fullSize() const { return (int)m_list.size(); }
};
} // namespace nachia
namespace nachia{
struct Graph {
public:
struct Edge{
int from, to;
void reverse(){ std::swap(from, to); }
int xorval() const { return from ^ to; }
};
Graph() : m_n(0), m_e(0), m_isUndir(false) {}
explicit Graph(int n, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {}
explicit Graph(int n, const std::vector<std::pair<int, int>>& edges, int undirected = false) : m_n(n), m_isUndir(undirected){
m_e.resize(edges.size());
for(std::size_t i=0; i<edges.size(); i++) m_e[i] = { edges[i].first, edges[i].second };
}
template<class Cin>
static Graph Input(Cin& cin, int n, bool undirected, int m, int offset = 0){
Graph res(n, undirected, m);
for(int i=0; i<m; i++){
int u, v; cin >> u >> v;
res[i].from = u - offset;
res[i].to = v - offset;
}
return res;
}
int numVertices() const noexcept { return m_n; }
int numEdges() const noexcept { return int(m_e.size()); }
int addNode() noexcept { return m_n++; }
int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; }
Edge& operator[](int ei) noexcept { return m_e[ei]; }
const Edge& operator[](int ei) const noexcept { return m_e[ei]; }
Edge& at(int ei) { return m_e.at(ei); }
const Edge& at(int ei) const { return m_e.at(ei); }
auto begin(){ return m_e.begin(); }
auto end(){ return m_e.end(); }
auto begin() const { return m_e.begin(); }
auto end() const { return m_e.end(); }
bool isUndirected() const noexcept { return m_isUndir; }
void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); }
void contract(int newV, const std::vector<int>& mapping){
assert(numVertices() == int(mapping.size()));
for(int i=0; i<numVertices(); i++) assert(0 <= mapping[i] && mapping[i] < newV);
for(auto& e : m_e){ e.from = mapping[e.from]; e.to = mapping[e.to]; }
m_n = newV;
}
std::vector<Graph> induce(int num, const std::vector<int>& mapping) const {
int n = numVertices();
assert(n == int(mapping.size()));
for(int i=0; i<n; i++) assert(-1 <= mapping[i] && mapping[i] < num);
std::vector<int> indexV(n), newV(num);
for(int i=0; i<n; i++) if(mapping[i] >= 0) indexV[i] = newV[mapping[i]]++;
std::vector<Graph> res; res.reserve(num);
for(int i=0; i<num; i++) res.emplace_back(newV[i], isUndirected());
for(auto e : m_e) if(mapping[e.from] == mapping[e.to] && mapping[e.to] >= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]);
return res;
}
CsrArray<int> getEdgeIndexArray(bool undirected) const {
std::vector<std::pair<int, int>> src;
src.reserve(numEdges() * (undirected ? 2 : 1));
for(int i=0; i<numEdges(); i++){
auto e = operator[](i);
src.emplace_back(e.from, i);
if(undirected) src.emplace_back(e.to, i);
}
return CsrArray<int>::Construct(numVertices(), src);
}
CsrArray<int> getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); }
CsrArray<int> getAdjacencyArray(bool undirected) const {
std::vector<std::pair<int, int>> src;
src.reserve(numEdges() * (undirected ? 2 : 1));
for(auto e : m_e){
src.emplace_back(e.from, e.to);
if(undirected) src.emplace_back(e.to, e.from);
}
return CsrArray<int>::Construct(numVertices(), src);
}
CsrArray<int> getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); }
private:
int m_n;
std::vector<Edge> m_e;
bool m_isUndir;
};
} // namespace nachia
namespace nachia{
struct HeavyLightDecomposition{
private:
int N;
std::vector<int> P;
std::vector<int> PP;
std::vector<int> PD;
std::vector<int> D;
std::vector<int> I;
std::vector<int> rangeL;
std::vector<int> rangeR;
public:
HeavyLightDecomposition(const Graph& tree, int root = 0) {
N = tree.numVertices();
D.assign(N, 0); D[root] = 2;
P.assign(N, 0);
for(auto [u,v] : tree){ D[u] += 1; D[v] += 1; P[u] ^= v; P[v] ^= u; }
std::vector<int> sz(N, 1);
std::vector<int> top(N);
std::vector<int> nx(N, -1);
int ipos = 0;
for(int v=0; v<N; v++) if(D[v] == 1) top[N-1-ipos++] = v;
for(int i=0; i<ipos; i++){
int v = top[N-1-i];
if(--D[P[v]] == 1) top[N-1-ipos++] = P[v];
P[P[v]] ^= v; sz[P[v]] += sz[v];
if(nx[P[v]] == -1 || sz[nx[P[v]]] < sz[v]) nx[P[v]] = v;
}
assert(ipos == N-1 && "HLD input tree traverse failed");
top[0] = root;
P[root] = -1;
PP.resize(N); for(int i=0; i<N; i++) PP[i] = i;
for(int v : top) if(nx[v] != -1) PP[nx[v]] = PP[v];
D.assign(N, 0);
for(int v : top) if(v != root) D[v] = D[P[v]]+1;
PD.assign(N,N); PD[root] = 0;
for(int v : top) if(v != root) PD[v] = std::min(PD[PP[v]], PD[P[v]]+1);
rangeL.assign(N,0);
sz[root] = 1;
for(int v : top){
if(v != root && PP[v] == v){
int p = P[v];
rangeL[v] = sz[p];
sz[p] += sz[v];
sz[v] = rangeL[v] + 1;
}
int w = nx[v];
if(w >= 0){
rangeL[w] = sz[v];
sz[v] += sz[w];
sz[w] = rangeL[w] + 1;
}
}
rangeR = std::move(sz);
for(int i=0; i<N; i++) top[rangeL[i]] = i;
I = std::move(top);
}
int numVertices() const { return N; }
int depth(int p) const { return D[p]; }
int toSeq(int vtx) const { return rangeL[vtx]; }
int toVtx(int seqidx) const { return I[seqidx]; }
int toSeq2In(int vtx) const { return rangeL[vtx] * 2 - D[vtx]; }
int toSeq2Out(int vtx) const { return rangeR[vtx] * 2 - D[vtx] - 1; }
int parentOf(int v) const { return P[v]; }
int heavyRootOf(int v) const { return PP[v]; }
int heavyChildOf(int v) const {
if(toSeq(v) == N-1) return -1;
int cand = toVtx(toSeq(v) + 1);
if(PP[v] == PP[cand]) return cand;
return -1;
}
int lca(int u, int v) const {
if(PD[u] < PD[v]) std::swap(u, v);
while(PD[u] > PD[v]) u = P[PP[u]];
while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; }
return (D[u] > D[v]) ? v : u;
/*
if(rangeL[u] > rangeL[v]) std::swap(u, v);
int h = rangeL[u];
while(h < rangeL[PP[v]]){ v = P[PP[v]]; }
return rangeL[v] <= h ? v : u;
*/
}
int dist(int u, int v) const {
return depth(u) + depth(v) - depth(lca(u,v)) * 2;
}
struct Range{
int l; int r;
int size() const { return r-l; }
bool includes(int x) const { return l <= x && x < r; }
};
std::vector<Range> path(int r, int c, bool include_root = true, bool reverse_path = false) const {
if(PD[c] < PD[r]) return {};
std::vector<Range> res(PD[c]-PD[r]+1);
for(int i=0; i<(int)res.size()-1; i++){
res[i] = { rangeL[PP[c]], rangeL[c]+1 };
c = P[PP[c]];
}
if(PP[r] != PP[c] || D[r] > D[c]) return {};
res.back() = { rangeL[r]+(include_root?0:1), rangeL[c]+1 };
if(res.back().l == res.back().r) res.pop_back();
if(!reverse_path) std::reverse(res.begin(),res.end());
else for(auto& a : res) a = { N - a.r, N - a.l };
return res;
}
Range subtree(int p) const { return { rangeL[p], rangeR[p] }; }
int median(int x, int y, int z) const {
return lca(x,y) ^ lca(y,z) ^ lca(x,z);
}
int la(int from, int to, int d) const {
if(d < 0) return -1;
int g = lca(from,to);
int dist0 = D[from] - D[g] * 2 + D[to];
if(dist0 < d) return -1;
int p = from;
if(D[from] - D[g] < d){ p = to; d = dist0 - d; }
while(D[p] - D[PP[p]] < d){
d -= D[p] - D[PP[p]] + 1;
p = P[PP[p]];
}
return I[rangeL[p] - d];
}
struct ChildrenIterRange {
struct Iter {
const HeavyLightDecomposition& hld; int s;
int operator*() const { return hld.toVtx(s); }
Iter& operator++(){
s += hld.subtree(hld.I[s]).size();
return *this;
}
Iter operator++(int) const { auto a = *this; return ++a; }
bool operator==(Iter& r) const { return s == r.s; }
bool operator!=(Iter& r) const { return s != r.s; }
};
const HeavyLightDecomposition& hld; int v;
Iter begin() const { return { hld, hld.rangeL[v] + 1 }; }
Iter end() const { return { hld, hld.rangeR[v] }; }
};
ChildrenIterRange children(int v) const {
return ChildrenIterRange{ *this, v };
}
};
} // namespace nachia
namespace nachia {
struct DsuFast{
private:
std::vector<int> w;
public:
DsuFast(int n = 0) : w(n, -1) {}
int leader(int u){
if(w[u] < 0) return u;
return w[u] = leader(w[u]);
}
int operator[](int u){ return leader(u); }
int merge(int u, int v){
u = leader(u);
v = leader(v);
if(u == v) return u;
if(-w[u] < -w[v]) std::swap(u, v);
w[u] += w[v];
w[v] = u;
return u;
}
int size(int u){ return -w[leader(u)]; }
bool same(int u, int v){ return leader(u) == leader(v); }
};
} // namespace nachia
ll solve(ll N, nachia::Graph tree, V<ll> X, V<ll> Y){
auto hld = nachia::HeavyLightDecomposition(tree);
for(auto& e : tree) if(hld.parentOf(e.to) != e.from) e.reverse();
auto einc = tree.getEdgeIndexArray();
ll ans = 0;
ll xsum = 0, ysum = 0;
nachia::DsuFast dsu(N);
V<ll> xv(N), yv(N);
REP(i,N){
ll x = 0, y = 0;
for(auto e : einc[i]){ x += X[e]; y += Y[e]; }
if(x > y){ xsum += x - y; xv[i] = x - y; }
if(y > x){ ysum += y - x; yv[i] = y - x; }
}
//cout << "xsum = " << xsum << " , ysum = " << ysum << endl;
if(ysum > xsum) return -1;
if((xsum + ysum) % 2 != 0) return -1;
REP(i,N-1){
auto [u,v] = tree[i];
if(X[i] || Y[i]) dsu.merge(u, v);
}
V<ll> zerocnt(N);
REP(i,N) if(xv[i] == 0 && yv[i] == 0) zerocnt[dsu.leader(i)]++;
ans = (xsum + ysum) / 2;
REP(i,N) if(dsu.leader(i) == i) if(dsu.size(i) == zerocnt[i]) ans++;
auto dfs = [&](auto& dfs, ll v, ll pe) -> void {
for(auto e : einc[v]) if(e != pe){
ll w = tree[e].xorval() ^ v;
dfs(dfs, w, e);
xv[v] += xv[w]; yv[v] += yv[w];
}
if(pe >= 0){
ll y1 = yv[v], y2 = ysum - yv[v];
ll x1 = xv[v], x2 = xsum - xv[v];
ll re = max(y1 - x1, y2 - x2);
if(X[pe] + Y[pe] < re) ans = -1;
}
};
dfs(dfs, 0, -1);
return ans;
}
void testcase(){
ll N; cin >> N;
nachia::Graph tree(N, 1);
V<ll> X(N), Y(N);
REP(i,N-1){ ll u,v; cin >> u >> v >> X[i] >> Y[i]; u--; v--; tree.addEdge(u,v); }
cout << solve(N, tree, X, Y) << "\n";
}
int main(){
cin.tie(0)->sync_with_stdio(0);
ll T; cin >> T; REP(t,T)
testcase();
return 0;
}
Submission Info
| Submission Time |
|
| Task |
C - Odd Even Counters |
| User |
Nachia |
| Language |
C++23 (GCC 15.2.0) |
| Score |
0 |
| Code Size |
16550 Byte |
| Status |
WA |
| Exec Time |
114 ms |
| Memory |
39236 KiB |
Judge Result
| Set Name |
Sample |
All |
| Score / Max Score |
0 / 0 |
0 / 800 |
| Status |
|
|
| Set Name |
Test Cases |
| Sample |
00-sample-001.txt |
| All |
00-sample-001.txt, 01-001.txt, 01-002.txt, 01-003.txt, 01-004.txt, 01-005.txt, 01-006.txt, 01-007.txt, 01-008.txt, 01-009.txt, 01-010.txt, 01-011.txt, 01-012.txt, 01-013.txt, 01-014.txt, 01-015.txt, 01-016.txt, 01-017.txt, 01-018.txt, 01-019.txt, 01-020.txt, 01-021.txt, 01-022.txt, 01-023.txt, 01-024.txt, 01-025.txt, 01-026.txt, 01-027.txt |
| Case Name |
Status |
Exec Time |
Memory |
| 00-sample-001.txt |
AC |
1 ms |
3556 KiB |
| 01-001.txt |
WA |
56 ms |
3644 KiB |
| 01-002.txt |
WA |
53 ms |
3764 KiB |
| 01-003.txt |
WA |
53 ms |
3796 KiB |
| 01-004.txt |
WA |
59 ms |
3680 KiB |
| 01-005.txt |
WA |
65 ms |
3516 KiB |
| 01-006.txt |
WA |
57 ms |
3724 KiB |
| 01-007.txt |
WA |
51 ms |
3980 KiB |
| 01-008.txt |
WA |
57 ms |
5088 KiB |
| 01-009.txt |
WA |
76 ms |
15448 KiB |
| 01-010.txt |
WA |
101 ms |
32636 KiB |
| 01-011.txt |
WA |
103 ms |
32596 KiB |
| 01-012.txt |
WA |
106 ms |
32580 KiB |
| 01-013.txt |
WA |
110 ms |
32664 KiB |
| 01-014.txt |
WA |
106 ms |
32596 KiB |
| 01-015.txt |
WA |
59 ms |
4468 KiB |
| 01-016.txt |
WA |
97 ms |
32644 KiB |
| 01-017.txt |
AC |
97 ms |
32644 KiB |
| 01-018.txt |
WA |
112 ms |
38488 KiB |
| 01-019.txt |
WA |
114 ms |
39236 KiB |
| 01-020.txt |
WA |
85 ms |
32640 KiB |
| 01-021.txt |
AC |
86 ms |
32668 KiB |
| 01-022.txt |
WA |
98 ms |
32640 KiB |
| 01-023.txt |
AC |
97 ms |
32660 KiB |
| 01-024.txt |
WA |
97 ms |
32612 KiB |
| 01-025.txt |
WA |
113 ms |
38836 KiB |
| 01-026.txt |
WA |
86 ms |
32648 KiB |
| 01-027.txt |
WA |
98 ms |
32508 KiB |