#ifndef LOCAL #define FAST_IO #endif // ============ #include #define OVERRIDE(a, b, c, d, ...) d #define REP2(i, n) for (i32 i = 0; i < (i32)(n); ++i) #define REP3(i, m, n) for (i32 i = (i32)(m); i < (i32)(n); ++i) #define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__) #define PER2(i, n) for (i32 i = (i32)(n)-1; i >= 0; --i) #define PER3(i, m, n) for (i32 i = (i32)(n)-1; i >= (i32)(m); --i) #define PER(...) OVERRIDE(__VA_ARGS__, PER3, PER2)(__VA_ARGS__) #define ALL(x) begin(x), end(x) #define LEN(x) (i32)(x.size()) using namespace std; using u32 = unsigned int; using u64 = unsigned long long; using i32 = signed int; using i64 = signed long long; using f64 = double; using f80 = long double; using pi = pair; using pl = pair; template using V = vector; template using VV = V>; template using VVV = V>>; template using VVVV = V>>>; template using PQR = priority_queue, greater>; template bool chmin(T &x, const T &y) { if (x > y) { x = y; return true; } return false; } template bool chmax(T &x, const T &y) { if (x < y) { x = y; return true; } return false; } template i32 lob(const V &arr, const T &v) { return (i32)(lower_bound(ALL(arr), v) - arr.begin()); } template i32 upb(const V &arr, const T &v) { return (i32)(upper_bound(ALL(arr), v) - arr.begin()); } template V argsort(const V &arr) { V ret(arr.size()); iota(ALL(ret), 0); sort(ALL(ret), [&](i32 i, i32 j) -> bool { if (arr[i] == arr[j]) { return i < j; } else { return arr[i] < arr[j]; } }); return ret; } #ifdef INT128 using u128 = __uint128_t; using i128 = __int128_t; #endif [[maybe_unused]] constexpr i32 INF = 1000000100; [[maybe_unused]] constexpr i64 INF64 = 3000000000000000100; struct SetUpIO { SetUpIO() { #ifdef FAST_IO ios::sync_with_stdio(false); cin.tie(nullptr); #endif cout << fixed << setprecision(15); } } set_up_io; void scan(char &x) { cin >> x; } void scan(u32 &x) { cin >> x; } void scan(u64 &x) { cin >> x; } void scan(i32 &x) { cin >> x; } void scan(i64 &x) { cin >> x; } void scan(f64 &x) { cin >> x; } void scan(string &x) { cin >> x; } template void scan(V &x) { for (T &ele : x) { scan(ele); } } void read() {} template void read(Head &head, Tail &...tail) { scan(head); read(tail...); } #define CHAR(...) \ char __VA_ARGS__; \ read(__VA_ARGS__); #define U32(...) \ u32 __VA_ARGS__; \ read(__VA_ARGS__); #define U64(...) \ u64 __VA_ARGS__; \ read(__VA_ARGS__); #define I32(...) \ i32 __VA_ARGS__; \ read(__VA_ARGS__); #define I64(...) \ i64 __VA_ARGS__; \ read(__VA_ARGS__); #define F64(...) \ f64 __VA_ARGS__; \ read(__VA_ARGS__); #define STR(...) \ string __VA_ARGS__; \ read(__VA_ARGS__); #define VEC(type, name, size) \ V name(size); \ read(name); #define VVEC(type, name, size1, size2) \ VV name(size1, V(size2)); \ read(name); // ============ #ifdef DEBUGF #else #define DBG(...) (void)0 #endif // ============ #include #include #include template struct Edge { using W = T; int from, to, id; W weight; Edge rev() const { return Edge{to, from, id, weight}; } }; template void debug(const Edge &e) { std::cerr << e.from << " -> " << e.to << " id = " << e.id << std::cerr << " weight = "; debug(e.weight); } template class Graph { public: using E = Edge; using W = T; static constexpr bool DIRECTED = DIR; struct Adjacency { using Iter = typename std::vector::iterator; Iter be, en; Iter begin() const { return be; } Iter end() const { return en; } int size() const { return (int)std::distance(be, en); } E &operator[](int idx) const { return be[idx]; } }; struct ConstAdjacency { using Iter = typename std::vector::const_iterator; Iter be, en; Iter begin() const { return be; } Iter end() const { return en; } int size() const { return (int)std::distance(be, en); } const E &operator[](int idx) const { return be[idx]; } }; private: int n, m; std::vector edges, csr; std::vector sep; bool built; public: Graph(int n) : n(n), m(0), built(false) {} int v() const { return n; } int e() const { return m; } int add_vertex() { return n++; } void add_edge(int from, int to, W weight = 1) { assert(0 <= from && from < n && 0 <= to && to < n); edges.emplace_back(E{from, to, m++, weight}); } void build() { sep.assign(n + 1, 0); csr.resize(DIRECTED ? m : 2 * m); for (const E &e : edges) { ++sep[e.from + 1]; if (!DIRECTED) { ++sep[e.to + 1]; } } for (int i = 0; i < n; ++i) { sep[i + 1] += sep[i]; } std::vector c = sep; for (const E &e : edges) { csr[c[e.from]++] = e; if (!DIRECTED) { csr[c[e.to]++] = e.rev(); } } built = true; } Adjacency operator[](int v) { assert(built && 0 <= v && v < n); return Adjacency{csr.begin() + sep[v], csr.begin() + sep[v + 1]}; } ConstAdjacency operator[](int v) const { assert(built && 0 <= v && v < n); return ConstAdjacency{csr.begin() + sep[v], csr.begin() + sep[v + 1]}; } }; // ============ // ============ #include constexpr bool is_prime(unsigned n) { if (n == 0 || n == 1) { return false; } for (unsigned i = 2; i * i <= n; ++i) { if (n % i == 0) { return false; } } return true; } constexpr unsigned mod_pow(unsigned x, unsigned y, unsigned mod) { unsigned ret = 1, self = x; while (y != 0) { if (y & 1) { ret = (unsigned)((unsigned long long)ret * self % mod); } self = (unsigned)((unsigned long long)self * self % mod); y /= 2; } return ret; } template constexpr unsigned primitive_root() { static_assert(is_prime(mod), "`mod` must be a prime number."); if (mod == 2) { return 1; } unsigned primes[32] = {}; int it = 0; { unsigned m = mod - 1; for (unsigned i = 2; i * i <= m; ++i) { if (m % i == 0) { primes[it++] = i; while (m % i == 0) { m /= i; } } } if (m != 1) { primes[it++] = m; } } for (unsigned i = 2; i < mod; ++i) { bool ok = true; for (int j = 0; j < it; ++j) { if (mod_pow(i, (mod - 1) / primes[j], mod) == 1) { ok = false; break; } } if (ok) return i; } return 0; } // y >= 1 template constexpr T safe_mod(T x, T y) { x %= y; if (x < 0) { x += y; } return x; } // y != 0 template constexpr T floor_div(T x, T y) { if (y < 0) { x *= -1; y *= -1; } if (x >= 0) { return x / y; } else { return -((-x + y - 1) / y); } } // y != 0 template constexpr T ceil_div(T x, T y) { if (y < 0) { x *= -1; y *= -1; } if (x >= 0) { return (x + y - 1) / y; } else { return -(-x / y); } } // b >= 1 // returns (g, x) s.t. g = gcd(a, b), a * x = g (mod b), 0 <= x < b / g // from ACL template std::pair extgcd(T a, T b) { a = safe_mod(a, b); T s = b, t = a, m0 = 0, m1 = 1; while (t) { T u = s / t; s -= t * u; m0 -= m1 * u; std::swap(s, t); std::swap(m0, m1); } if (m0 < 0) { m0 += b / s; } return std::pair(s, m0); } // b >= 1 // returns (g, x, y) s.t. g = gcd(a, b), a * x + b * y = g, 0 <= x < b / g, |y| < max(2, |a| / g) template std::tuple extgcd2(T a, T b) { T _a = safe_mod(a, b); T quot = (a - _a) / b; T x00 = 0, x01 = 1, y0 = b; T x10 = 1, x11 = -quot, y1 = _a; while (y1) { T u = y0 / y1; x00 -= u * x10; x01 -= u * x11; y0 -= u * y1; std::swap(x00, x10); std::swap(x01, x11); std::swap(y0, y1); } if (x00 < 0) { x00 += b / y0; x01 -= a / y0; } return std::tuple(y0, x00, x01); } // gcd(x, m) == 1 template T inv_mod(T x, T m) { return extgcd(x, m).second; } // ============ i64 loop(i64 k, const V &a) { DBG(k, a); i32 n = LEN(a); if (n % 2 == 1) { V ops(n, 0); REP(i, 1, n) { ops[i] = a[i] - ops[i - 1]; } i64 more = a[0] - (ops[0] + ops[n - 1]); if (more % 2 != 0) { return -1; } more /= 2; REP(i, n) { if (i % 2 == 0) { ops[i] += more; } else { ops[i] -= more; } } DBG(ops); i64 ans = 0; REP(i, n) { if (ops[i] < 0 || (0 < ops[i] && ops[i] < k)) { return -1; } ans += ceil_div(ops[i], 2 * k); } return ans; } assert(n % 2 == 0); V ops(n, 0); REP(i, 1, n) { ops[i] = a[i] - ops[i - 1]; } if (ops[0] + ops[n - 1] != a[0]) { return -1; } DBG(k, n, a, ops); // +x -x +x -x ... +x -x i64 low = -INF64, high = INF64; REP(i, n / 2) { chmax(low, -ops[2 * i]); chmin(high, ops[2 * i + 1]); } if (low > high) { return -1; } // mendou i64 ans = 0; REP(i, n) { ans += ceil_div(ops[i], 2 * k); } // tasukete!!!! V> add; REP(i, n / 2) { { i64 val = ops[2 * i]; i64 md = safe_mod(val, 2 * k); if (md == 0) { add.emplace_back(1, 2 * k, 1); } else if (md >= 2) { add.emplace_back(2 * k + 1 - md, 2 * k, 1); } } { i64 val = ops[2 * i + 1]; i64 md = safe_mod(val, 2 * k); if (md != 0) { add.emplace_back(md, 2 * k, -1); } } } DBG(ans, low, high, add); V> ban; if (k > 1) { REP(i, n / 2) { { i64 val = ops[2 * i]; // 1 <= val + x < k // 1 - val <= x < k - val i64 l = 1 - val, r = k - val; if (floor_div(l, 2 * k) < floor_div(r - 1, 2 * k)) { ban.emplace_back(safe_mod(l, 2 * k), 2 * k, floor_div(l, 2 * k)); ban.emplace_back(0, safe_mod(r, 2 * k), floor_div(r, 2 * k)); } else { ban.emplace_back(safe_mod(l, 2 * k), safe_mod(r - 1, 2 * k) + 1, floor_div(l, 2 * k)); } } { i64 val = ops[2 * i]; // 1 <= val - x < k // val - k < x <= val - 1 i64 l = val - k + 1, r = val; // [l, r) if (floor_div(l, 2 * k) < floor_div(r - 1, 2 * k)) { ban.emplace_back(safe_mod(l, 2 * k), 2 * k, floor_div(l, 2 * k)); ban.emplace_back(0, safe_mod(r, 2 * k), floor_div(r, 2 * k)); } else { ban.emplace_back(safe_mod(l, 2 * k), safe_mod(r - 1, 2 * k) + 1, floor_div(l, 2 * k)); } } } } DBG(ban); V pos; pos.push_back(0); pos.push_back(2 * k); for (auto [l, r, v] : add) { pos.push_back(l); pos.push_back(r); } for (auto [l, r, v] : ban) { pos.push_back(l); pos.push_back(r); } pos.push_back(safe_mod(low, 2 * k)); pos.push_back(safe_mod(high + 1, 2 * k)); sort(ALL(pos)); pos.erase(unique(ALL(pos)), end(pos)); i32 m = LEN(pos); VV push(m), remov(m); V lu(m, 0); for (auto [l, r, v] : add) { lu[lob(pos, l)] += v; lu[lob(pos, r)] -= v; } REP(i, m - 1) { lu[i + 1] += lu[i]; } for (auto [l, r, v] : ban) { l = lob(pos, l); r = lob(pos, r); push[l].push_back(v); remov[r].push_back(v); } multiset ms; i32 diff = INF; REP(i, m - 1) { for (i64 v : remov[i]) { ms.erase(ms.find(v)); } for (i64 v : push[i]) { ms.insert(v); } i64 md = pos[i]; // md + 2 * k * x >= low // x >= ceil((low - md) / (2 * k)) i64 x = ceil_div(low - md, 2 * k); bool ok = false; while (md + 2 * x * k <= high) { if (!ms.contains(x)) { ok = true; break; } ++x; } if (ok) { chmin(diff, lu[i]); } } ans += diff; return ans; } void solve() { I32(n); I64(k); VEC(i64, a, n); Graph<> g(n); REP(i, n) { I32(u, v); --u; --v; g.add_edge(u, v); } g.build(); V deg(n); REP(i, n) { deg[i] = LEN(g[i]); } queue que; i64 ans = 0; REP(i, n) { if (deg[i] == 1) { que.push(i); } } while (!que.empty()) { i32 v = que.front(); que.pop(); i32 u = -1; for (auto e : g[v]) { if (deg[e.to] >= 2) { u = e.to; } } assert(u != -1); if (a[v] < 0 || (0 < a[v] && a[v] < k)) { cout << -1 << '\n'; return; } a[u] -= a[v]; ans += ceil_div(a[v], 2 * k); if (--deg[u] == 1) { que.push(u); } } DBG(deg, a, ans); REP(v, n) { if (deg[v] != 2) { continue; } V arr; i32 cur = v; i32 prv = -1; while (true) { arr.push_back(a[cur]); deg[cur] = -1; i32 to = -1; for (auto e : g[cur]) { if (deg[e.to] == 2 && e.to != prv) { to = e.to; break; } } if (to == -1) { break; } prv = exchange(cur, to); } i64 sub = loop(k, arr); if (sub == -1) { cout << -1 << '\n'; return; } ans += sub; } cout << ans << '\n'; } int main() { i32 t = 1; // cin >> t; while (t--) { solve(); } }