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
AC × 1
AC × 4
WA × 24
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