///////////////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

using namespace std;

///////////////////////////////////////////////////////////////////////////////

#define DEBUG 0

#define pb push_back
#define V vector
#define M unordered_map
#define S static

#define rep(i,n) for(ll i=0LL;i<n;++i)
#define srep(i,s,n) for(ll i=s;i<n;++i)
#define rrep(i,n) for(ll i=n-1LL;i>=0LL;--i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define CIN(x) do { \
    assert(!cin.eof()); \
    cin >> x; \
    assert(!cin.fail()); \
} while(0);
#if DEBUG
#define debug_print(...) _debug_print(__VA_ARGS__)
#define debug_printf(...) printf(__VA_ARGS__)
#define debug_print_time _debug_print_time
#else // DEBUG
#define debug_print(...)
#define debug_printf(...)
#define debug_print_time
#endif // DEBUG

typedef long long ll;
typedef unsigned long long ull;
typedef tuple<ll, ll> t2;
typedef tuple<ll, ll, ll> t3;
typedef tuple<ll, ll, ll, ll> t4;
typedef tuple<ll, ll, ll, ll, ll> t5;
template <typename T>
using priority_queue_incr = priority_queue<T, V<T>, greater<T>>;

///////////////////////////////////////////////////////////////////////////////

template <typename TT, typename T>
T get_m(M<TT, T> &m, TT k, T default_value)
{
    if (m.find(k) == m.end()) return m[k] = default_value;
    return m[k];
}

template <typename TT, typename T>
void incr_m(M<TT, T> &m, TT k)
{
    if (m.find(k) == m.end()) m[k] = 0;
    m[k]++;
}

struct UnionFind
{
    ull *parent, *count, *rank;

    UnionFind(ull n) {
        parent = new ull[n+1];
        count = new ull[n+1];
        rank = new ull[n+1];
        for (ull i = 0ULL; i < n+1; ++i) {
            parent[i] = i;
            count[i] = 1;
            rank[i] = 0;
        }
    }

    ~UnionFind() {
        delete rank;
        delete count;
        delete parent;
    }

    ull root(ull i) {
        if (parent[i] == i) return i;
        parent[i] = root(parent[i]);
        return parent[i];
    }

    void unite(ull i, ull j) {
        ull rooti = root(i);
        ull rootj = root(j);

        if (rooti == rootj) return;

        if (rank[rootj] < rank[rooti]) {
            parent[i] = parent[j] = parent[rootj] = rooti;
            count[rooti] += count[rootj];
        }
        else {
            parent[i] = parent[j] = parent[rooti] = rootj;
            count[rootj] += count[rooti];
            if (rank[rootj] == rank[rooti]) rank[rootj]++;
        }
    }

    bool same(ull i, ull j) {
        return root(i) == root(j);
    }
};

struct UnionFindM
{
    M<ull, ull> parent, count, rank;

    ull root(ull i) {
        ull parent_i = get_m(parent, i, i);
        if (parent_i == i) return i;
        return parent[i] = root(parent_i);
    }

    void unite(ull i, ull j) {
        ull rooti = root(i);
        ull rootj = root(j);

        if (rooti == rootj) return;

        if (get_m(rank, rootj, 0ULL) < get_m(rank, rooti, 0ULL)) {
            parent[i] = parent[j] = parent[rootj] = rooti;
            count[rooti] = get_m(count, rooti, 1ULL) + get_m(count, rootj, 1ULL);
        }
        else {
            parent[i] = parent[j] = parent[rooti] = rootj;
            count[rootj] = get_m(count, rootj, 1ULL) + get_m(count, rooti, 1ULL);
            if (get_m(rank, rootj, 0ULL) == get_m(rank, rooti, 0ULL)) rank[rootj]++;
        }
    }

    bool same(ull i, ull j) {
        return root(i) == root(j);
    }
};

struct BIT
{
    ll *tree;
    ll size;

    BIT(ll n, ll init) {
        tree = new ll[n+1];
        size = n;
        this->init(init);
    }

    void init(ll init) {
        memset(tree, 0, sizeof(ll) * (size+1));
        rep (i0, size) {
            ll idx = i0 + 1LL;
            while (idx <= size) {
                tree[idx] += init;
                idx += (idx & (-idx));
            }
        }
    }

    // idx is 1 origin
    void add(ll idx, ll x) {
        assert(idx > 0LL);
        while (idx <= size) {
            tree[idx] += x;
            idx += (idx & (-idx));
        }
    }

    // idx is 1 origin
    ll sum(ll idx) {
        assert(idx > 0LL);
        ll ret = 0LL;
        while (idx > 0LL) {
            ret += tree[idx];
            idx -= (idx & (-idx));
        }
        return ret;
    }
};

struct MaxFlow {
    V<ll> links[1005];
    ll capacities[1005][1005];
    ll nodes;

    MaxFlow(ll nodes) {
        // i == 0       --> S
        // i == nodes+1 --> T
        rep (i, nodes+2LL) links[i].clear();
        memset(capacities, 0, sizeof(capacities));
        this->nodes = nodes;
    }

    void add_path(ll a, ll b, ll capacity) {
        links[a].pb(b);
        links[b].pb(a);
        capacities[a][b] = capacity;
        capacities[b][a] = 0LL;
    }

    ll solve(void) {
        deque<V<ll>> q;
        ll ret = 0LL;

        for ( ; ; q.clear()) {

            V<ll> start;
            start.pb(0);
            q.push_front(start);

            bool checked[nodes+2];
            memset(checked, 0, sizeof(checked));

            V<ll> found;

            for ( ; !(q.empty()); ) {
                V<ll> path = q.front(); q.pop_front();
                ll last = path[path.size()-1];

                if (checked[last]) continue;
                if (last == nodes+1) {
                    found = path;
                    break;
                }

                checked[last] = true;
                for (auto next : (links[last])) {
                    if (capacities[last][next] == 0) continue;
                    V<ll> newpath(path);
                    newpath.pb(next);
                    q.push_front(newpath);
                }
            }

            if (found.size() == 0) {
                break;
            }
            else {
                ll flowcount = capacities[found[0]][found[1]];
                rep (i, found.size()-1) {
                    ll src = found[i];
                    ll dst = found[i+1];
                    flowcount = min(flowcount, capacities[src][dst]);
                }
                rep (i, found.size()-1) {
                    ll src = found[i];
                    ll dst = found[i+1];
                    capacities[src][dst] -= flowcount;
                    capacities[dst][src] += flowcount;
                }
                ret += flowcount;
            }
        }

        return ret;
    }
};

template <typename T>
struct SegmentTree {
    T *nodes;
    t2 *ranges;  // [start, end)
    ll nodecount;
    ll itemcount;
    T unit;
    T (*op)(T, T);

    SegmentTree(ll itemcount, T unit, T op(T, T)) {
        ll orig_itemcount = itemcount;
        this->itemcount = 1LL;
        while (this->itemcount < orig_itemcount) this->itemcount *= 2LL;
        nodecount = this->itemcount * 2 - 1;
        nodes = new T[nodecount];
        ranges = new t2[nodecount];
        this->unit = unit;
        this->op = op;

        ll start = 0LL;
        ll end = this->itemcount;
        ll len = this->itemcount;

        rep (i, nodecount) {
            nodes[i] = unit;
            ranges[i] = t2(start, end);
            if (end >= this->itemcount) {
                len /= 2LL;
                start = 0LL;
                end = len;
            }
            else {
                start = end;
                end = start + len;
            }
        }
    }

    void update(ll k, T v) {
        ll idx = k + itemcount - 1LL;
        nodes[idx] = v;
        idx = (idx - 1LL) / 2LL;

        for ( ; idx >= 0; idx = (idx - 1LL) / 2LL) {
            nodes[idx] = op(nodes[idx * 2LL + 1LL],
                            nodes[idx * 2LL + 2LL]);
            if (!idx) break;
        }
    }

    // query to [start, end)
    T query(ll start, ll end) const {
        return _query(start, end, 0LL);
    }

    T _query(ll start, ll end, ll idx) const {
        ll rstart = get<0>(ranges[idx]);
        ll rend = get<1>(ranges[idx]);

        if (start <= rstart && rend <= end) {
            return nodes[idx];
        }
        if (rend <= start || end <= rstart) {
            return unit;
        }
        T left = _query(start, end, idx * 2LL + 1LL);
        T right = _query(start, end, idx * 2LL + 2LL);
        return op(left, right);
    }

};

void llin(ll &a)
{
    CIN(a);
}

void llinl1(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a;
        CIN(a);
        v.push_back(a);
    }
}

void llinl2(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b;
        CIN(a >> b);
        v.push_back(t2(a, b));
    }
}

void llinl3(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b, c;
        CIN(a >> b >> c);
        v.push_back(t3(a, b, c));
    }
}

void llinl4(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b, c, d;
        CIN(a >> b >> c >> d);
        v.push_back(t4(a, b, c, d));
    }
}

void llina(auto &v, ll count)
{
    llinl1(v, count);
}

template <typename T>
T min(const V<T> v)
{
    T ret = v[0];
    for (auto i : v) ret = min(ret, i);
    return ret;
}

template <typename T>
T max(const V<T> v)
{
    T ret = v[0];
    for (auto i : v) ret = max(ret, i);
    return ret;
}

ll absll(ll x)
{
    if (x < 0) return -x;
    return x;
}

ll mod_mlt(ll x, ll y, ll mod)
{
    ll ret = 0LL;
    x %= mod;

    while (y) {
        if (y & 1LL) {
            ret += x;
            ret %= mod;
        }
        y >>= 1;
        x <<= 1;
        x %= mod;
    }

    return ret;
}

// O(log(exp))
ll mod_pow(ll base, ll exp, ll mod)
{
    ll ret = 1LL;

    for ( ; exp; ) {
        if (exp & 1LL) {
            ret *= base;
            ret %= mod;
        }
        base = (base * base) % mod;
        exp >>= 1;
    }

    return ret;
}

// O(log(mod))
ll mod_inv(ll x, ll mod)
{
    // available only when mod is prime
    return mod_pow(x, mod - 2LL, mod);
}

ll gcm(ll x, ll y)
{
    while (y != 0) {
        ll z = x % y;
        x = y;
        y = z;
    }
    return x;
}

template <typename T>
void sort(V<T> &v)
{
    sort(v.begin(), v.end());
}

template <typename T>
void sort_reverse(V<T> &v)
{
    sort(v.begin(), v.end(), greater<T>());
}

void get_divisors(V<ll> &retlist, ll x)
{
    for (ll i = 1LL; i < sqrt(x) + 3LL; ++i) {
        if (x % i == 0LL) {
            retlist.push_back(i);
            retlist.push_back(x / i);
        }
    }
}

// returns factors and 1
void get_factors(V<ll> &retlist, ll x)
{
    retlist.pb(1LL);
    for (ll i = 2LL; i < (ll)(sqrt(x)) + 3LL; ++i) {
        while (x % i == 0LL) {
            retlist.pb(i);
            x /= i;
        }
    }
    retlist.pb(x);
}

bool is_prime(ll x)
{
    V<ll> factors, factors2;

    get_factors(factors, x);

    for (auto factor : factors) {
        if (factor > 1) factors2.pb(factor);
    }

    return factors2.size() == 1 && x == factors2[0];
}

template <typename T>
void intersection(const set<T> &a, const set<T> &b,
                  set<T> &result)
{
    set_intersection(ALL(a), ALL(b), inserter(result, result.end()));
}

ull combination(ll x, ll y)
{
    if (y > x / 2LL) y = x - y;

    ull ret = 1LL;
    for (ll i = 0LL; i < y; ++i) {
        ret *= x--;
        ret /= (i + 1LL);
    }

    return ret;
}

ull mod_combination(ll x, ll y, ll mod)
{
    if (y > x / 2LL) y = x - y;

    ll ret = 1;

    for (ll i = 0LL; i < y; ++i) {
        ret = (ret * x--) % mod;
        ret = (ret * mod_inv(i + 1LL, mod)) % mod;
    }

    return ret;
}

void make_perms(ll perms[], ll perm_invs[], ll size, ll mod)
{
    perms[0] = 1LL;
    srep (i, 1, size) {
        perms[i] = perms[i-1] * i;
        perms[i] %= mod;
   }

    rep (i, size) {
        perm_invs[i] = mod_inv(perms[i], mod);
    }
}

void make_linklist(const V<t2> &srclist, V<ll> dstlist[])
{
    for (auto src : srclist) {
        ll a = get<0>(src);
        ll b = get<1>(src);
        dstlist[a].pb(b);
        dstlist[b].pb(a);
    }
}

void make_parental_relation(const V<ll> linklist[], ll root, ll n,
                            ll parent[], V<ll> children[], ll level[])
{
    queue<ll> q;
    bool checked[n+1];

    memset(checked, 0, sizeof(checked));

    q.push(root);
    checked[root] = true;
    parent[root] = root;
    level[root] = 0LL;

    for ( ; !(q.empty()); ) {
        ll now = q.front(); q.pop();
        for (auto next : linklist[now]) {
            if (checked[next]) continue;
            q.push(next);
            checked[next] = true;
            parent[next] = now;
            children[now].pb(next);
            level[next] = level[now] + 1LL;
        }
    }
}

void make_subtree_sizes(const ll child_count[], const ll parents[],
                        ll subtree_sizes[], ll n)
{
    ll remain_count[n+1LL];
    memcpy(remain_count, child_count, sizeof(remain_count));

    queue<ll> q;
    srep (node, 1LL, n+1LL) {
        subtree_sizes[node] = 1LL;
        if (remain_count[node] > 0) continue;
        q.push(node);
    }

    while (!q.empty()) {
        ll node = q.front(); q.pop();
        ll parent = parents[node];
        if (node == parent) continue;
        remain_count[parent]--;
        subtree_sizes[parent] += subtree_sizes[node];
        if (remain_count[parent] == 0LL) q.push(parent);
    }
}

void get_centroids(const V<ll> children[], const ll subtree_sizes[],
                   ll root, ll n, V<ll> &centroids)
{
    queue<ll> q;
    q.push(root);

    while (!q.empty()) {
        ll now = q.front(); q.pop();
        bool is_centroid = true;
        for (auto child : children[now]) {
            q.push(child);
            if (subtree_sizes[child] > n / 2LL) is_centroid = false;
        }
        if (n - subtree_sizes[now] > n / 2LL) is_centroid = false;
        if (is_centroid) centroids.pb(now);
    }

    assert(centroids.size() == 1LL || centroids.size() == 2LL);
}

#define POW_ANCESTOR_MAXSIZE   20

// preprocess for get_common_ancestor()
void make_pow_ancestor(const ll parent[], ll n,
                       ll (*pow_ancestor)[POW_ANCESTOR_MAXSIZE])
{
    rep (i, n) pow_ancestor[i+1][0] = parent[i+1];

    for (int pow2 = 1; pow(2, pow2) <= n; ++pow2) {
        rep (i0, n) {
            int i = i0+1;
            ll prev = pow_ancestor[i][pow2-1];
            pow_ancestor[i][pow2] = pow_ancestor[prev][pow2-1];
        }
    }
}

ll get_common_ancestor(ll n, ll x, ll y,
                       const ll (*pow_ancestor)[POW_ANCESTOR_MAXSIZE],
                       const ll level[])
{
    if (level[x] < level[y]) {
        ll diff = level[y] - level[x];
        for ( ; diff; ) {
            ll bit = diff & -diff;
            y = pow_ancestor[y][(int)log2(bit)];
            diff -= bit;
        }
    }
    else {
        ll diff = level[x] - level[y];
        for ( ; diff; ) {
            ll bit = diff & -diff;
            x = pow_ancestor[x][(int)log2(bit)];
            diff -= bit;
        }
    }

    if (x == y) return x;

    rrep (i, (int)log2(n)+1) {
        if (pow_ancestor[x][i] != pow_ancestor[y][i]) {
            x = pow_ancestor[x][i];
            y = pow_ancestor[y][i];
        }
    }

    return pow_ancestor[x][0];
}

void kmp_init(const string &pattern, ll kmp_next[])
{
    kmp_next[0] = -1LL;

    ll plen = pattern.size();
    ll prefix_end = -1;

    rep (suffix_end, pattern.size()) {
        while (prefix_end >= 0 && pattern[suffix_end] != pattern[prefix_end]) {
            prefix_end = kmp_next[prefix_end];
        }
        kmp_next[suffix_end+1] = ++prefix_end;
    }

    kmp_next[0] = 0LL;
}

// founds ... list of text's idx of match position. start position idx.
void kmp_search(const string &text, const string &pattern, const ll kmp_next[],
                V<ll> &founds)
{
    ll text_size = text.size();
    ll pattern_size = pattern.size();
    ll text_start = 0LL;
    ll pattern_idx = 0LL;

    assert(pattern_size <= text_size);

    for ( ; ; ) {
        if (text_start + pattern_idx >= text_size) break;
        if (pattern_idx >= pattern_size) break;

        if (text[text_start+pattern_idx] == pattern[pattern_idx]) {
            pattern_idx++;
            if (pattern_idx == pattern_size) {
                founds.pb(text_start);
                pattern_idx = kmp_next[pattern_idx];
                text_start += (pattern_size - pattern_idx);
            }
        }

        else {
            text_start += (pattern_idx - kmp_next[pattern_idx]);
            pattern_idx = kmp_next[pattern_idx];
            if (pattern_idx == 0LL && text[text_start] != pattern[0]) {
                text_start++;
            }
        }
    }
}

void z_algorithm(ll matchcounts[], const string &str)
{
    ll n = str.size();
    ll base_idx = 0LL;
    memset(matchcounts, 0, sizeof(ll) * n);

    srep (idx, 1LL, n) {

        ll checked_len = base_idx + matchcounts[base_idx];

        if (idx + matchcounts[idx-base_idx] < checked_len) {
            matchcounts[idx] = matchcounts[idx-base_idx];
            continue;
        }

        ll start = max(0LL, base_idx + matchcounts[base_idx] - idx);
        matchcounts[idx] = start;
        srep (cmp, start, n-idx) {
            if (str[cmp] == str[idx+cmp]) matchcounts[idx]++;
            else break;
        }
        base_idx = idx;

    }

    matchcounts[0] = n;
}

void _debug_print(auto x)
{
    cout << x << endl;
}

void _debug_print(const t2 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    cout << "-- " << x1 << " -- " << x2 << endl;
}

void _debug_print(const t3 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    ll x3 = get<2>(x);
    cout << "-- " << x1 << " -- " << x2 << " -- " << x3 << endl;
}

void _debug_print(const t4 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    ll x3 = get<2>(x);
    ll x4 = get<3>(x);
    cout << "-- " << x1 << " -- " << x2
        << " -- " << x3 << " -- " << x4 << endl;
}

template <typename T>
void _debug_print(T xarray[], ll n)
{
    rep (i, n) _debug_print(xarray[i]);
}

template <typename T>
void _debug_print(const V<T> &xlist)
{
    for (auto x : xlist) {
        cout << "-- ";
        _debug_print(x);
    }
}

template <typename T>
void _debug_print(const set<T> &xset)
{
    for (auto x : xset) {
        cout << "-- ";
        _debug_print(x);
    }
}

template <typename TT, typename T>
void _debug_print(const M<TT, T> &xlist)
{
    for (auto x : xlist) {
        TT k = x.first;
        T v = x.second;
        cout << "====" << endl;
        cout << "K=";
        _debug_print(k);
        cout << "V=";
        _debug_print(v);
    }
}

void _debug_print_time(const char *prefix)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    struct tm *tm = localtime(&tv.tv_sec);
    printf("-- %s %02d:%02d:%02d.%06ld\n",
           prefix, tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}

///////////////////////////////////////////////////////////////////////////////

void make_edges(const V<t3> &srclist, V<t2> dstlist[])
{
    for (auto src : srclist) {
        ll a = get<0>(src);
        ll b = get<1>(src);
        ll x = get<2>(src);
        dstlist[a].pb(t2(b, x));
        dstlist[b].pb(t2(a, x));
    }
}

void _main();
int main()
{
    cout << setprecision(12);
    _main();
    return 0;
}

void _main()
{
    ll n; llin(n);
    S V<t3> uvxlist; llinl3(uvxlist, n-1);

    S V<t2> edgex_list[1003];
    make_edges(uvxlist, edgex_list);

    S V<ll> edge_list[1003];
    srep (a, 1, n+1) {
        for (auto edgex : edgex_list[a]) {
            ll b = get<0>(edgex);
            edge_list[a].pb(b);
        }
    }

    S ll xlist[20000003];
    for (auto uvx : uvxlist) {
        ll u = get<0>(uvx);
        ll v = get<1>(uvx);
        ll x = get<2>(uvx);
        xlist[u * 10000LL + v] = x;
        xlist[v * 10000LL + u] = x;
    }

    ll root = -1LL;
    srep (v, 1, n+1) {
        if (edge_list[v].size() == 1) root = v;
        if (edge_list[v].size() == 2) {
            cout << "NO" << endl;
            return;
        }
    }
    assert(root > 0LL);
    assert(root <= n);

    S ll parents[1003];
    S V<ll> children[1003];
    S ll levels[1003];
    make_parental_relation(edge_list, root, n, parents, children, levels);

    S ll refs[1003];
    S queue<ll> q;
    srep (v, 1, n+1) {
        refs[v] = children[v].size();
        if (!refs[v]) q.push(v);
    }

    S V<t3> anslist;
    S ll saved_v1[1003];
    S ll saved_x1[1003];
    S ll saved_v2[1003];
    S ll saved_x2[1003];
    rep (i, 1003) saved_v1[i] = -1LL;
    rep (i, 1003) saved_x1[i] = -1LL;
    rep (i, 1003) saved_v2[i] = -1LL;
    rep (i, 1003) saved_x2[i] = -1LL;

    while (!q.empty()) {
        ll v = q.front(); q.pop();
        ll pv = parents[v];
        refs[pv]--;

        if (pv == root) {
            assert(!refs[root]);
            ll x = xlist[root * 10000LL + v];
            if (saved_v1[v] < 0LL) {
                anslist.pb(t3(root, v, x));
            }
            else {
                ll v1 = saved_v1[v];
                ll x1 = saved_x1[v];
                ll v2 = saved_v2[v];
                ll x2 = saved_x2[v];
                assert(x1 + x2 == x);
                anslist.pb(t3(root, v1, x1));
                anslist.pb(t3(root, v2, x2));
            }
            continue;
        }

        if (!refs[pv]) {
            V<ll> vs;
            ll vm = -1LL;

            for (auto cv : children[pv]) {
                if (saved_v1[cv] < 0LL) vs.pb(cv);
                else vm = cv;
            }

            if (vm > 0LL) {
                ll v1 = saved_v1[vm];
                ll x1 = saved_x1[vm];
                ll v2 = saved_v2[vm];
                ll x2 = saved_x2[vm];
                for (auto cv : children[pv]) {
                    if (cv == vm) continue;
                    if (saved_v1[cv] < 0LL) {
                        anslist.pb(t3(v1, cv, xlist[pv * 10000LL + cv]));
                        x1 -= xlist[pv * 10000LL + cv];
                    }
                    else {
                        ll cv1 = saved_v1[cv];
                        ll cx1 = saved_x1[cv];
                        ll cv2 = saved_v2[cv];
                        ll cx2 = saved_x2[cv];
                        anslist.pb(t3(v1, cv1, cx1));
                        x1 -= cx1;
                        anslist.pb(t3(v1, cv2, cx2));
                        x1 -= cx2;
                    }
                }
                ll ppv = parents[pv];
                ll ppx = xlist[ppv * 10000LL + pv];
                ll xi = ((x1 + x2) - ppx) / 2LL;
                anslist.pb(t3(v1, v2, xi));
                x1 -= xi;
                x2 -= xi;
                assert(x1 + x2 == ppx);
                saved_v1[pv] = v1;
                saved_x1[pv] = x1;
                saved_v2[pv] = v2;
                saved_x2[pv] = x2;
            }

            else {
                assert(vs.size() >= 2LL);
                ll v1 = vs[0];
                ll x1 = xlist[pv * 10000LL + v1];
                ll v2 = vs[1];
                ll x2 = xlist[pv * 10000LL + v2];
                for (auto cv : children[pv]) {
                    if (v1 == cv) continue;
                    if (v2 == cv) continue;
                    if (saved_v1[cv] < 0LL) {
                        anslist.pb(t3(v1, cv, xlist[pv * 10000LL + cv]));
                        x1 -= xlist[pv * 10000LL + cv];
                    }
                    else {
                        ll cv1 = saved_v1[cv];
                        ll cx1 = saved_x1[cv];
                        ll cv2 = saved_v2[cv];
                        ll cx2 = saved_x2[cv];
                        anslist.pb(t3(v1, cv1, cx1));
                        x1 -= cx1;
                        anslist.pb(t3(v1, cv2, cx2));
                        x1 -= cx2;
                    }
                }
                ll ppv = parents[pv];
                ll ppx = xlist[ppv * 10000LL + pv];
                ll xi = ((x1 + x2) - ppx) / 2LL;
                anslist.pb(t3(v1, v2, xi));
                x1 -= xi;
                x2 -= xi;
                assert(x1 + x2 == ppx);
                saved_v1[pv] = v1;
                saved_x1[pv] = x1;
                saved_v2[pv] = v2;
                saved_x2[pv] = x2;
            }

            q.push(pv);
        }

    }

    cout << "YES" << endl;
    cout << anslist.size() << endl;
    for (auto ans :anslist) {
        ll v1 = get<0>(ans);
        ll v2 = get<1>(ans);
        ll x = get<2>(ans);
        printf("%lld %lld %lld\n", v1, v2, x);
    }

}

///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

using namespace std;

///////////////////////////////////////////////////////////////////////////////

#define DEBUG 0

#define pb push_back
#define V vector
#define M unordered_map
#define S static

#define rep(i,n) for(ll i=0LL;i<n;++i)
#define srep(i,s,n) for(ll i=s;i<n;++i)
#define rrep(i,n) for(ll i=n-1LL;i>=0LL;--i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define CIN(x) do { \
    assert(!cin.eof()); \
    cin >> x; \
    assert(!cin.fail()); \
} while(0);
#if DEBUG
#define debug_print(...) _debug_print(__VA_ARGS__)
#define debug_printf(...) printf(__VA_ARGS__)
#define debug_print_time _debug_print_time
#else // DEBUG
#define debug_print(...)
#define debug_printf(...)
#define debug_print_time
#endif // DEBUG

typedef long long ll;
typedef unsigned long long ull;
typedef tuple<ll, ll> t2;
typedef tuple<ll, ll, ll> t3;
typedef tuple<ll, ll, ll, ll> t4;
typedef tuple<ll, ll, ll, ll, ll> t5;
template <typename T>
using priority_queue_incr = priority_queue<T, V<T>, greater<T>>;

///////////////////////////////////////////////////////////////////////////////

template <typename TT, typename T>
T get_m(M<TT, T> &m, TT k, T default_value)
{
    if (m.find(k) == m.end()) return m[k] = default_value;
    return m[k];
}

template <typename TT, typename T>
void incr_m(M<TT, T> &m, TT k)
{
    if (m.find(k) == m.end()) m[k] = 0;
    m[k]++;
}

struct UnionFind
{
    ull *parent, *count, *rank;

    UnionFind(ull n) {
        parent = new ull[n+1];
        count = new ull[n+1];
        rank = new ull[n+1];
        for (ull i = 0ULL; i < n+1; ++i) {
            parent[i] = i;
            count[i] = 1;
            rank[i] = 0;
        }
    }

    ~UnionFind() {
        delete rank;
        delete count;
        delete parent;
    }

    ull root(ull i) {
        if (parent[i] == i) return i;
        parent[i] = root(parent[i]);
        return parent[i];
    }

    void unite(ull i, ull j) {
        ull rooti = root(i);
        ull rootj = root(j);

        if (rooti == rootj) return;

        if (rank[rootj] < rank[rooti]) {
            parent[i] = parent[j] = parent[rootj] = rooti;
            count[rooti] += count[rootj];
        }
        else {
            parent[i] = parent[j] = parent[rooti] = rootj;
            count[rootj] += count[rooti];
            if (rank[rootj] == rank[rooti]) rank[rootj]++;
        }
    }

    bool same(ull i, ull j) {
        return root(i) == root(j);
    }
};

struct UnionFindM
{
    M<ull, ull> parent, count, rank;

    ull root(ull i) {
        ull parent_i = get_m(parent, i, i);
        if (parent_i == i) return i;
        return parent[i] = root(parent_i);
    }

    void unite(ull i, ull j) {
        ull rooti = root(i);
        ull rootj = root(j);

        if (rooti == rootj) return;

        if (get_m(rank, rootj, 0ULL) < get_m(rank, rooti, 0ULL)) {
            parent[i] = parent[j] = parent[rootj] = rooti;
            count[rooti] = get_m(count, rooti, 1ULL) + get_m(count, rootj, 1ULL);
        }
        else {
            parent[i] = parent[j] = parent[rooti] = rootj;
            count[rootj] = get_m(count, rootj, 1ULL) + get_m(count, rooti, 1ULL);
            if (get_m(rank, rootj, 0ULL) == get_m(rank, rooti, 0ULL)) rank[rootj]++;
        }
    }

    bool same(ull i, ull j) {
        return root(i) == root(j);
    }
};

struct BIT
{
    ll *tree;
    ll size;

    BIT(ll n, ll init) {
        tree = new ll[n+1];
        size = n;
        this->init(init);
    }

    void init(ll init) {
        memset(tree, 0, sizeof(ll) * (size+1));
        rep (i0, size) {
            ll idx = i0 + 1LL;
            while (idx <= size) {
                tree[idx] += init;
                idx += (idx & (-idx));
            }
        }
    }

    // idx is 1 origin
    void add(ll idx, ll x) {
        assert(idx > 0LL);
        while (idx <= size) {
            tree[idx] += x;
            idx += (idx & (-idx));
        }
    }

    // idx is 1 origin
    ll sum(ll idx) {
        assert(idx > 0LL);
        ll ret = 0LL;
        while (idx > 0LL) {
            ret += tree[idx];
            idx -= (idx & (-idx));
        }
        return ret;
    }
};

struct MaxFlow {
    V<ll> links[1005];
    ll capacities[1005][1005];
    ll nodes;

    MaxFlow(ll nodes) {
        // i == 0       --> S
        // i == nodes+1 --> T
        rep (i, nodes+2LL) links[i].clear();
        memset(capacities, 0, sizeof(capacities));
        this->nodes = nodes;
    }

    void add_path(ll a, ll b, ll capacity) {
        links[a].pb(b);
        links[b].pb(a);
        capacities[a][b] = capacity;
        capacities[b][a] = 0LL;
    }

    ll solve(void) {
        deque<V<ll>> q;
        ll ret = 0LL;

        for ( ; ; q.clear()) {

            V<ll> start;
            start.pb(0);
            q.push_front(start);

            bool checked[nodes+2];
            memset(checked, 0, sizeof(checked));

            V<ll> found;

            for ( ; !(q.empty()); ) {
                V<ll> path = q.front(); q.pop_front();
                ll last = path[path.size()-1];

                if (checked[last]) continue;
                if (last == nodes+1) {
                    found = path;
                    break;
                }

                checked[last] = true;
                for (auto next : (links[last])) {
                    if (capacities[last][next] == 0) continue;
                    V<ll> newpath(path);
                    newpath.pb(next);
                    q.push_front(newpath);
                }
            }

            if (found.size() == 0) {
                break;
            }
            else {
                ll flowcount = capacities[found[0]][found[1]];
                rep (i, found.size()-1) {
                    ll src = found[i];
                    ll dst = found[i+1];
                    flowcount = min(flowcount, capacities[src][dst]);
                }
                rep (i, found.size()-1) {
                    ll src = found[i];
                    ll dst = found[i+1];
                    capacities[src][dst] -= flowcount;
                    capacities[dst][src] += flowcount;
                }
                ret += flowcount;
            }
        }

        return ret;
    }
};

template <typename T>
struct SegmentTree {
    T *nodes;
    t2 *ranges;  // [start, end)
    ll nodecount;
    ll itemcount;
    T unit;
    T (*op)(T, T);

    SegmentTree(ll itemcount, T unit, T op(T, T)) {
        ll orig_itemcount = itemcount;
        this->itemcount = 1LL;
        while (this->itemcount < orig_itemcount) this->itemcount *= 2LL;
        nodecount = this->itemcount * 2 - 1;
        nodes = new T[nodecount];
        ranges = new t2[nodecount];
        this->unit = unit;
        this->op = op;

        ll start = 0LL;
        ll end = this->itemcount;
        ll len = this->itemcount;

        rep (i, nodecount) {
            nodes[i] = unit;
            ranges[i] = t2(start, end);
            if (end >= this->itemcount) {
                len /= 2LL;
                start = 0LL;
                end = len;
            }
            else {
                start = end;
                end = start + len;
            }
        }
    }

    void update(ll k, T v) {
        ll idx = k + itemcount - 1LL;
        nodes[idx] = v;
        idx = (idx - 1LL) / 2LL;

        for ( ; idx >= 0; idx = (idx - 1LL) / 2LL) {
            nodes[idx] = op(nodes[idx * 2LL + 1LL],
                            nodes[idx * 2LL + 2LL]);
            if (!idx) break;
        }
    }

    // query to [start, end)
    T query(ll start, ll end) const {
        return _query(start, end, 0LL);
    }

    T _query(ll start, ll end, ll idx) const {
        ll rstart = get<0>(ranges[idx]);
        ll rend = get<1>(ranges[idx]);

        if (start <= rstart && rend <= end) {
            return nodes[idx];
        }
        if (rend <= start || end <= rstart) {
            return unit;
        }
        T left = _query(start, end, idx * 2LL + 1LL);
        T right = _query(start, end, idx * 2LL + 2LL);
        return op(left, right);
    }

};

void llin(ll &a)
{
    CIN(a);
}

void llinl1(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a;
        CIN(a);
        v.push_back(a);
    }
}

void llinl2(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b;
        CIN(a >> b);
        v.push_back(t2(a, b));
    }
}

void llinl3(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b, c;
        CIN(a >> b >> c);
        v.push_back(t3(a, b, c));
    }
}

void llinl4(auto &v, ll count)
{
    for (ll i = 0LL; i < count ; ++i) {
        ll a, b, c, d;
        CIN(a >> b >> c >> d);
        v.push_back(t4(a, b, c, d));
    }
}

void llina(auto &v, ll count)
{
    llinl1(v, count);
}

template <typename T>
T min(const V<T> v)
{
    T ret = v[0];
    for (auto i : v) ret = min(ret, i);
    return ret;
}

template <typename T>
T max(const V<T> v)
{
    T ret = v[0];
    for (auto i : v) ret = max(ret, i);
    return ret;
}

ll absll(ll x)
{
    if (x < 0) return -x;
    return x;
}

ll mod_mlt(ll x, ll y, ll mod)
{
    ll ret = 0LL;
    x %= mod;

    while (y) {
        if (y & 1LL) {
            ret += x;
            ret %= mod;
        }
        y >>= 1;
        x <<= 1;
        x %= mod;
    }

    return ret;
}

// O(log(exp))
ll mod_pow(ll base, ll exp, ll mod)
{
    ll ret = 1LL;

    for ( ; exp; ) {
        if (exp & 1LL) {
            ret *= base;
            ret %= mod;
        }
        base = (base * base) % mod;
        exp >>= 1;
    }

    return ret;
}

// O(log(mod))
ll mod_inv(ll x, ll mod)
{
    // available only when mod is prime
    return mod_pow(x, mod - 2LL, mod);
}

ll gcm(ll x, ll y)
{
    while (y != 0) {
        ll z = x % y;
        x = y;
        y = z;
    }
    return x;
}

template <typename T>
void sort(V<T> &v)
{
    sort(v.begin(), v.end());
}

template <typename T>
void sort_reverse(V<T> &v)
{
    sort(v.begin(), v.end(), greater<T>());
}

void get_divisors(V<ll> &retlist, ll x)
{
    for (ll i = 1LL; i < sqrt(x) + 3LL; ++i) {
        if (x % i == 0LL) {
            retlist.push_back(i);
            retlist.push_back(x / i);
        }
    }
}

// returns factors and 1
void get_factors(V<ll> &retlist, ll x)
{
    retlist.pb(1LL);
    for (ll i = 2LL; i < (ll)(sqrt(x)) + 3LL; ++i) {
        while (x % i == 0LL) {
            retlist.pb(i);
            x /= i;
        }
    }
    retlist.pb(x);
}

bool is_prime(ll x)
{
    V<ll> factors, factors2;

    get_factors(factors, x);

    for (auto factor : factors) {
        if (factor > 1) factors2.pb(factor);
    }

    return factors2.size() == 1 && x == factors2[0];
}

template <typename T>
void intersection(const set<T> &a, const set<T> &b,
                  set<T> &result)
{
    set_intersection(ALL(a), ALL(b), inserter(result, result.end()));
}

ull combination(ll x, ll y)
{
    if (y > x / 2LL) y = x - y;

    ull ret = 1LL;
    for (ll i = 0LL; i < y; ++i) {
        ret *= x--;
        ret /= (i + 1LL);
    }

    return ret;
}

ull mod_combination(ll x, ll y, ll mod)
{
    if (y > x / 2LL) y = x - y;

    ll ret = 1;

    for (ll i = 0LL; i < y; ++i) {
        ret = (ret * x--) % mod;
        ret = (ret * mod_inv(i + 1LL, mod)) % mod;
    }

    return ret;
}

void make_perms(ll perms[], ll perm_invs[], ll size, ll mod)
{
    perms[0] = 1LL;
    srep (i, 1, size) {
        perms[i] = perms[i-1] * i;
        perms[i] %= mod;
   }

    rep (i, size) {
        perm_invs[i] = mod_inv(perms[i], mod);
    }
}

void make_linklist(const V<t2> &srclist, V<ll> dstlist[])
{
    for (auto src : srclist) {
        ll a = get<0>(src);
        ll b = get<1>(src);
        dstlist[a].pb(b);
        dstlist[b].pb(a);
    }
}

void make_parental_relation(const V<ll> linklist[], ll root, ll n,
                            ll parent[], V<ll> children[], ll level[])
{
    queue<ll> q;
    bool checked[n+1];

    memset(checked, 0, sizeof(checked));

    q.push(root);
    checked[root] = true;
    parent[root] = root;
    level[root] = 0LL;

    for ( ; !(q.empty()); ) {
        ll now = q.front(); q.pop();
        for (auto next : linklist[now]) {
            if (checked[next]) continue;
            q.push(next);
            checked[next] = true;
            parent[next] = now;
            children[now].pb(next);
            level[next] = level[now] + 1LL;
        }
    }
}

void make_subtree_sizes(const ll child_count[], const ll parents[],
                        ll subtree_sizes[], ll n)
{
    ll remain_count[n+1LL];
    memcpy(remain_count, child_count, sizeof(remain_count));

    queue<ll> q;
    srep (node, 1LL, n+1LL) {
        subtree_sizes[node] = 1LL;
        if (remain_count[node] > 0) continue;
        q.push(node);
    }

    while (!q.empty()) {
        ll node = q.front(); q.pop();
        ll parent = parents[node];
        if (node == parent) continue;
        remain_count[parent]--;
        subtree_sizes[parent] += subtree_sizes[node];
        if (remain_count[parent] == 0LL) q.push(parent);
    }
}

void get_centroids(const V<ll> children[], const ll subtree_sizes[],
                   ll root, ll n, V<ll> &centroids)
{
    queue<ll> q;
    q.push(root);

    while (!q.empty()) {
        ll now = q.front(); q.pop();
        bool is_centroid = true;
        for (auto child : children[now]) {
            q.push(child);
            if (subtree_sizes[child] > n / 2LL) is_centroid = false;
        }
        if (n - subtree_sizes[now] > n / 2LL) is_centroid = false;
        if (is_centroid) centroids.pb(now);
    }

    assert(centroids.size() == 1LL || centroids.size() == 2LL);
}

#define POW_ANCESTOR_MAXSIZE   20

// preprocess for get_common_ancestor()
void make_pow_ancestor(const ll parent[], ll n,
                       ll (*pow_ancestor)[POW_ANCESTOR_MAXSIZE])
{
    rep (i, n) pow_ancestor[i+1][0] = parent[i+1];

    for (int pow2 = 1; pow(2, pow2) <= n; ++pow2) {
        rep (i0, n) {
            int i = i0+1;
            ll prev = pow_ancestor[i][pow2-1];
            pow_ancestor[i][pow2] = pow_ancestor[prev][pow2-1];
        }
    }
}

ll get_common_ancestor(ll n, ll x, ll y,
                       const ll (*pow_ancestor)[POW_ANCESTOR_MAXSIZE],
                       const ll level[])
{
    if (level[x] < level[y]) {
        ll diff = level[y] - level[x];
        for ( ; diff; ) {
            ll bit = diff & -diff;
            y = pow_ancestor[y][(int)log2(bit)];
            diff -= bit;
        }
    }
    else {
        ll diff = level[x] - level[y];
        for ( ; diff; ) {
            ll bit = diff & -diff;
            x = pow_ancestor[x][(int)log2(bit)];
            diff -= bit;
        }
    }

    if (x == y) return x;

    rrep (i, (int)log2(n)+1) {
        if (pow_ancestor[x][i] != pow_ancestor[y][i]) {
            x = pow_ancestor[x][i];
            y = pow_ancestor[y][i];
        }
    }

    return pow_ancestor[x][0];
}

void kmp_init(const string &pattern, ll kmp_next[])
{
    kmp_next[0] = -1LL;

    ll plen = pattern.size();
    ll prefix_end = -1;

    rep (suffix_end, pattern.size()) {
        while (prefix_end >= 0 && pattern[suffix_end] != pattern[prefix_end]) {
            prefix_end = kmp_next[prefix_end];
        }
        kmp_next[suffix_end+1] = ++prefix_end;
    }

    kmp_next[0] = 0LL;
}

// founds ... list of text's idx of match position. start position idx.
void kmp_search(const string &text, const string &pattern, const ll kmp_next[],
                V<ll> &founds)
{
    ll text_size = text.size();
    ll pattern_size = pattern.size();
    ll text_start = 0LL;
    ll pattern_idx = 0LL;

    assert(pattern_size <= text_size);

    for ( ; ; ) {
        if (text_start + pattern_idx >= text_size) break;
        if (pattern_idx >= pattern_size) break;

        if (text[text_start+pattern_idx] == pattern[pattern_idx]) {
            pattern_idx++;
            if (pattern_idx == pattern_size) {
                founds.pb(text_start);
                pattern_idx = kmp_next[pattern_idx];
                text_start += (pattern_size - pattern_idx);
            }
        }

        else {
            text_start += (pattern_idx - kmp_next[pattern_idx]);
            pattern_idx = kmp_next[pattern_idx];
            if (pattern_idx == 0LL && text[text_start] != pattern[0]) {
                text_start++;
            }
        }
    }
}

void z_algorithm(ll matchcounts[], const string &str)
{
    ll n = str.size();
    ll base_idx = 0LL;
    memset(matchcounts, 0, sizeof(ll) * n);

    srep (idx, 1LL, n) {

        ll checked_len = base_idx + matchcounts[base_idx];

        if (idx + matchcounts[idx-base_idx] < checked_len) {
            matchcounts[idx] = matchcounts[idx-base_idx];
            continue;
        }

        ll start = max(0LL, base_idx + matchcounts[base_idx] - idx);
        matchcounts[idx] = start;
        srep (cmp, start, n-idx) {
            if (str[cmp] == str[idx+cmp]) matchcounts[idx]++;
            else break;
        }
        base_idx = idx;

    }

    matchcounts[0] = n;
}

void _debug_print(auto x)
{
    cout << x << endl;
}

void _debug_print(const t2 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    cout << "-- " << x1 << " -- " << x2 << endl;
}

void _debug_print(const t3 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    ll x3 = get<2>(x);
    cout << "-- " << x1 << " -- " << x2 << " -- " << x3 << endl;
}

void _debug_print(const t4 &x)
{
    ll x1 = get<0>(x);
    ll x2 = get<1>(x);
    ll x3 = get<2>(x);
    ll x4 = get<3>(x);
    cout << "-- " << x1 << " -- " << x2
        << " -- " << x3 << " -- " << x4 << endl;
}

template <typename T>
void _debug_print(T xarray[], ll n)
{
    rep (i, n) _debug_print(xarray[i]);
}

template <typename T>
void _debug_print(const V<T> &xlist)
{
    for (auto x : xlist) {
        cout << "-- ";
        _debug_print(x);
    }
}

template <typename T>
void _debug_print(const set<T> &xset)
{
    for (auto x : xset) {
        cout << "-- ";
        _debug_print(x);
    }
}

template <typename TT, typename T>
void _debug_print(const M<TT, T> &xlist)
{
    for (auto x : xlist) {
        TT k = x.first;
        T v = x.second;
        cout << "====" << endl;
        cout << "K=";
        _debug_print(k);
        cout << "V=";
        _debug_print(v);
    }
}

void _debug_print_time(const char *prefix)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    struct tm *tm = localtime(&tv.tv_sec);
    printf("-- %s %02d:%02d:%02d.%06ld\n",
           prefix, tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}

///////////////////////////////////////////////////////////////////////////////

void make_edges(const V<t3> &srclist, V<t2> dstlist[])
{
    for (auto src : srclist) {
        ll a = get<0>(src);
        ll b = get<1>(src);
        ll x = get<2>(src);
        dstlist[a].pb(t2(b, x));
        dstlist[b].pb(t2(a, x));
    }
}

void _main();
int main()
{
    cout << setprecision(12);
    _main();
    return 0;
}

void _main()
{
    ll n; llin(n);
    S V<t3> uvxlist; llinl3(uvxlist, n-1);

    S V<t2> edgex_list[1003];
    make_edges(uvxlist, edgex_list);

    S V<ll> edge_list[1003];
    srep (a, 1, n+1) {
        for (auto edgex : edgex_list[a]) {
            ll b = get<0>(edgex);
            edge_list[a].pb(b);
        }
    }

#define BORDER (10000LL)

    S ll xlist[20000003];
    for (auto uvx : uvxlist) {
        ll u = get<0>(uvx);
        ll v = get<1>(uvx);
        ll x = get<2>(uvx);
        xlist[u * BORDER + v] = x;
        xlist[v * BORDER + u] = x;
    }

    ll root = -1LL;
    srep (v, 1, n+1) {
        if (edge_list[v].size() == 1) root = v;
        if (edge_list[v].size() == 2) {
            cout << "NO" << endl;
            return;
        }
    }
    assert(root > 0LL);
    assert(root <= n);

    S ll parents[1003];
    S V<ll> children[1003];
    S ll levels[1003];
    make_parental_relation(edge_list, root, n, parents, children, levels);

    S ll saved_v1[1003];
    S ll saved_x1[1003];
    S ll saved_v2[1003];
    S ll saved_x2[1003];
    rep (i, 1003) saved_v1[i] = -1LL;
    rep (i, 1003) saved_x1[i] = 0LL;
    rep (i, 1003) saved_v2[i] = -1LL;
    rep (i, 1003) saved_x2[i] = 0LL;

    S ll refs[1003];
    S queue<ll> q;
    srep (v, 1, n+1) {
        refs[v] = children[v].size();
        if (!refs[v]) {
            q.push(v);
            ll pv = parents[v];
            saved_v1[v] = v;
            saved_x1[v] = xlist[pv * BORDER + v];
        }
    }

    S V<t3> anslist;

    while (!q.empty()) {
        ll v = q.front(); q.pop();
        ll pv = parents[v];
        refs[pv]--;

        if (refs[pv]) continue;

        if (pv == root) {
            ll v1 = saved_v1[v];
            ll x1 = saved_x1[v];
            ll v2 = saved_v2[v];
            ll x2 = saved_x2[v];
            debug_printf("x1=%lld x2=%lld x=%lld\n",
                        x1, x2, xlist[pv * BORDER + v]);
            assert(x1 + x2 == xlist[pv * BORDER + v]);
            anslist.pb(t3(root, v1, x1));
            if (v2 > 0LL) anslist.pb(t3(root, v2, x2));
            continue;
        }

        v = -1;

        ll va = children[pv][0];
        ll vb = children[pv][1];

        srep (chidx, 2, children[pv].size()) {
            v = children[pv][chidx];

            ll cv = saved_v1[v];
            ll cx = saved_x1[v];
            anslist.pb(t3(saved_v1[va], cv, cx));
            saved_x1[va] -= cx;

            cv = saved_v2[v];
            cx = saved_x2[v];
            if (cv > 0) {
                anslist.pb(t3(saved_v1[va], cv, cx));
                saved_x1[va] -= cx;
            }
        }

        if (saved_v2[va] > 0) {
            anslist.pb(t3(saved_v1[vb], saved_v2[va], saved_x2[va]));
            saved_x1[vb] -= saved_x2[va];
        }
        if (saved_v2[vb] > 0) {
            anslist.pb(t3(saved_v1[va], saved_v2[vb], saved_x2[vb]));
            saved_x1[va] -= saved_x2[vb];
        }

        ll ppv = parents[pv];
        ll px = xlist[ppv * BORDER + pv];
        ll inx = (saved_x1[va] + saved_x1[vb] - px) / 2LL;
        anslist.pb(t3(saved_v1[va], saved_v1[vb], inx));
        saved_x1[va] -= inx;
        saved_x1[vb] -= inx;

        q.push(pv);
        saved_v1[pv] = saved_v1[va];
        saved_x1[pv] = saved_x1[va];
        saved_v2[pv] = saved_v1[vb];
        saved_x2[pv] = saved_x1[vb];
    }

    cout << "YES" << endl;
    cout << anslist.size() << endl;
    for (auto ans :anslist) {
        ll v1 = get<0>(ans);
        ll v2 = get<1>(ans);
        ll x = get<2>(ans);
        printf("%lld %lld %lld\n", v1, v2, x);
    }

}

///////////////////////////////////////////////////////////////////////////////


#include <bits/stdc++.h>
#define fir first
#define sec second
#define fr fir.fir
#define to fir.sec
#define MAX_N 100000
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> opr;
template <class T> inline void read(T &x) {
	x = 0; int c = getchar(), f = 1;
	for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
	for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n; vector <int> leaf;
vector <int> G[MAX_N+5], E[MAX_N+5];
vector <opr> ans;
int DFS(int u, int fa) {
	for (int v : G[u]) if (v ^ fa)
		return DFS(v, u);
	return u;
}
int find(int u, int fa, int tar) {
	if (u == tar) return u;
	for (int v : G[u]) if (v ^ fa)
		if (find(v, u, tar)) return v;
	return 0;
}
void add(int u, int v, int x) {
//	cout << "P: " << u << ' ' << v << ' ' << x << endl;
	if ((int)G[v].size() == 1)
		{ans.push_back(opr(pii(u, v), x)); return;}
	int pr = find(v, 0, u); leaf.clear();
	for (int r : G[v]) if (r ^ pr) {
		leaf.push_back(DFS(r, v));
		if ((int)leaf.size() == 2) break;
	}
//	cout << "leaf " << leaf[0] << ' ' << leaf[1] << endl;
	ans.push_back(opr(pii(u, leaf[0]), x/2));
	ans.push_back(opr(pii(u, leaf[1]), x/2));
	ans.push_back(opr(pii(leaf[0], leaf[1]), -x/2));
}
int main() {
	read(n);
	for (int i = 1, u, v, c; i < n; i++)
		read(u), read(v), read(c),
		G[u].push_back(v), E[u].push_back(c),
		G[v].push_back(u), E[v].push_back(c);
	for (int i = 1; i <= n; i++)
		if ((int)G[i].size() == 2)
			return puts("NO"), 0;
	for (int u = 1, p; u <= n; u++)
		for (int i = 0; i < (int)G[u].size(); i++) {
			int v = G[u][i], c = E[u][i];
			if (u >= v) continue;
		//	cout << u << ' ' << v << endl;
			if ((int)G[u].size() == 1) add(u, v, c);
			else
				leaf.clear(), p = DFS(u, v),
				add(p, v, c), add(p, u, -c);
		}
	puts("YES"), printf("%d\n", (int)ans.size());
	for (opr op : ans)
		printf("%d %d %d\n", op.fr, op.to, op.sec);
	return 0;
}


#include <bits/stdc++.h>
#define fir first
#define sec second
#define fr fir.fir
#define to fir.sec
#define MAX_N 100000
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> opr;
template <class T> inline void read(T &x) {
	x = 0; int c = getchar(), f = 1;
	for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
	for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n; vector <int> leaf;
vector <int> G[MAX_N+5], E[MAX_N+5];
vector <opr> ans;
void DFS(int u, int fa) {
	if ((int)leaf.size() == 2) return;
	if ((int)G[u].size() == 1) leaf.push_back(u);
	for (int v : G[u]) if (v ^ fa) DFS(v, u);
}
int find(int u, int fa, int tar) {
	if (u == tar) return u;
	for (int v : G[u]) if (v ^ fa)
		if (find(v, u, tar)) return v;
	return 0;
}
void add(int u, int v, int x) {
	if ((int)G[v].size() == 1)
		{ans.push_back(opr(pii(u, v), x)); return;}
	leaf.clear(), DFS(v, find(u, 0, v));
	ans.push_back(opr(pii(u, leaf[0]), x/2));
	ans.push_back(opr(pii(u, leaf[1]), x/2));
	ans.push_back(opr(pii(leaf[0], leaf[1]), -x/2));
}
int main() {
	read(n);
	for (int i = 1, u, v, c; i < n; i++)
		read(u), read(v), read(c),
		G[u].push_back(v), E[u].push_back(c),
		G[v].push_back(u), E[v].push_back(c);
	for (int i = 1; i <= n; i++)
		if ((int)G[i].size() == 2)
			return puts("NO"), 0;
	for (int u = 1, p; u <= n; u++)
		for (int i = 0; i < (int)G[u].size(); i++) {
			int v = G[u][i], c = E[u][i];
			if (u >= v) continue;
			if ((int)G[u].size() == 1) add(u, v, c);
			else
				leaf.clear(), DFS(u, v), p = leaf[0],
				add(p, v, c), add(p, u, -c);
		}
	puts("YES"), printf("%d\n", (int)ans.size());
	for (opr op : ans)
		printf("%d %d %d\n", op.fr, op.to, op.sec);
	return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; (i) < (int) (n); (i) ++)
using namespace std;

int main() {
        int n;
        scanf("%d", &n);
        vector<vector<pair<int, int>>> g(n);
        rep(i, n - 1) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                a --, b --;
                g[a].push_back({b, c});
                g[b].push_back({a, c});
        }
        rep(i, n) {
                if (g[i].size() != 1 && g[i].size() < 3) {
                        puts("NO");
                        return 0;
                }
        }
        vector<pair<pair<int, int>, int>> res;
        function<void (int, int)> dfs = [&](int u, int prev) {
                for (auto e : g[u]) {
                        int v = e.first;
                        if (v == prev) continue;
                        int val = e.second;
                        function<int (int, int)> gl = [&](int u, int prev) {
                                if (g[u].size() == 1) return u;
                                for (auto e : g[u]) {
                                        int v = e.first;
                                        if (v == prev) continue;
                                        return gl(v, u);
                                }
                                return 0;
                        };

                        vector<int> ul;
                        for (auto e : g[u]) {
                                int vv = e.first;
                                if (vv == v) continue;
                                int l = gl(vv, u);
                                ul.push_back(l);
                                if (ul.size() == 2) break;
                        }

                        if (g[v].size() == 1) {
                                res.push_back({{ul[0], v}, val / 2});
                                res.push_back({{ul[1], v}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                        } else {
                                vector<int> bl;
                                for (auto e : g[v]) {
                                        int vv = e.first;
                                        if (vv == u) continue;
                                        int l = gl(vv, v);
                                        bl.push_back(l);
                                        if (bl.size() == 2) break;
                                }
                                res.push_back({{ul[0], bl[0]}, val / 2});
                                res.push_back({{ul[1], bl[1]}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                                res.push_back({{bl[0], bl[1]}, - val / 2});
                        }

                        dfs(v, u);
                }
        };
        dfs(0, -1);
        map<pair<int, int>, long long> ans;
        rep(i, res.size()) {
                int a = res[i].first.first;
                int b = res[i].first.second;
                ans[make_pair(min(a, b), max(a, b))] += res[i].second;
        }
        printf("%d\n", (int) ans.size());
        for (auto a : ans) {
                printf("%d %d %lld\n", a.first.first + 1, a.first.second + 1, a.second);
        }
        return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; (i) < (int) (n); (i) ++)
using namespace std;

int main() {
        int n;
        scanf("%d", &n);
        vector<vector<pair<int, int>>> g(n);
        rep(i, n - 1) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                a --, b --;
                g[a].push_back({b, c});
                g[b].push_back({a, c});
        }
        rep(i, n) {
                if (g[i].size() != 1 && g[i].size() < 3) {
                        puts("NO");
                        return 0;
                }
        }
        vector<pair<pair<int, int>, int>> res;
        function<void (int, int)> dfs = [&](int u, int prev) {
                for (auto e : g[u]) {
                        int v = e.first;
                        if (v == prev) continue;
                        int val = e.second;
                        function<int (int, int)> gl = [&](int u, int prev) {
                                if (g[u].size() == 1) return u;
                                for (auto e : g[u]) {
                                        int v = e.first;
                                        if (v == prev) continue;
                                        return gl(v, u);
                                }
                                return 0;
                        };

                        vector<int> ul;
                        for (auto e : g[u]) {
                                int vv = e.first;
                                if (vv == v) continue;
                                int l = gl(vv, u);
                                ul.push_back(l);
                                if (ul.size() == 2) break;
                        }

                        if (g[v].size() == 1) {
                                res.push_back({{ul[0], v}, val / 2});
                                res.push_back({{ul[1], v}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                        } else {
                                vector<int> bl;
                                for (auto e : g[v]) {
                                        int vv = e.first;
                                        if (vv == u) continue;
                                        int l = gl(vv, v);
                                        bl.push_back(l);
                                        if (bl.size() == 2) break;
                                }
                                res.push_back({{ul[0], bl[0]}, val / 2});
                                res.push_back({{ul[1], bl[1]}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                                res.push_back({{bl[0], bl[1]}, - val / 2});
                        }

                        dfs(v, u);
                }
        };
        dfs(0, -1);
        map<pair<int, int>, long long> ans;
        rep(i, res.size()) {
                int a = res[i].first.first;
                int b = res[i].first.second;
                ans[make_pair(min(a, b), max(a, b))] += res[i].second;
        }
        puts("YES");
        printf("%d\n", (int) ans.size());
        for (auto a : ans) {
                printf("%d %d %lld\n", a.first.first + 1, a.first.second + 1, a.second);
        }
        return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; (i) < (int) (n); (i) ++)
using namespace std;

int main() {
        int n;
        scanf("%d", &n);
        vector<vector<pair<int, int>>> g(n);
        rep(i, n - 1) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                a --, b --;
                g[a].push_back({b, c});
                g[b].push_back({a, c});
        }
        rep(i, n) {
                if (g[i].size() != 1 && g[i].size() < 3) {
                        puts("NO");
                        return 0;
                }
        }
        int root = -1;
        rep(i, n) {
                if (g[i].size() != 1) {
                        root = i;
                        break;
                }
        }
        if (root == -1) {
                printf("YES\n1\n1 2 %d\n", g[0][0].second);
                return 0;
        }
        vector<pair<pair<int, int>, int>> res;
        function<void (int, int)> dfs = [&](int u, int prev) {
                for (auto e : g[u]) {
                        int v = e.first;
                        if (v == prev) continue;
                        int val = e.second;
                        function<int (int, int)> gl = [&](int u, int prev) {
                                if (g[u].size() == 1) return u;
                                for (auto e : g[u]) {
                                        int v = e.first;
                                        if (v == prev) continue;
                                        return gl(v, u);
                                }
                                return 0;
                        };

                        vector<int> ul;
                        for (auto e : g[u]) {
                                int vv = e.first;
                                if (vv == v) continue;
                                int l = gl(vv, u);
                                ul.push_back(l);
                                if (ul.size() == 2) break;
                        }

                        if (g[v].size() == 1) {
                                res.push_back({{ul[0], v}, val / 2});
                                res.push_back({{ul[1], v}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                        } else {
                                vector<int> bl;
                                for (auto e : g[v]) {
                                        int vv = e.first;
                                        if (vv == u) continue;
                                        int l = gl(vv, v);
                                        bl.push_back(l);
                                        if (bl.size() == 2) break;
                                }
                                res.push_back({{ul[0], bl[0]}, val / 2});
                                res.push_back({{ul[1], bl[1]}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                                res.push_back({{bl[0], bl[1]}, - val / 2});
                        }

                        dfs(v, u);
                }
        };
        dfs(root, -1);
        /*
        map<pair<int, int>, long long> ans;
        rep(i, res.size()) {
                int a = res[i].first.first;
                int b = res[i].first.second;
                ans[make_pair(min(a, b), max(a, b))] += res[i].second;
        }
        printf("YES\n%d\n", (int) ans.size());
        */
        printf("YES\n%d\n", (int) res.size());
        for (auto a : res) {
                printf("%d %d %d\n", a.first.first + 1, a.first.second + 1, a.second);
        }
        return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; (i) < (int) (n); (i) ++)
using namespace std;

int main() {
        int n;
        scanf("%d", &n);
        vector<vector<pair<int, int>>> g(n);
        rep(i, n - 1) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                a --, b --;
                g[a].push_back({b, c});
                g[b].push_back({a, c});
        }
        rep(i, n) {
                if (g[i].size() != 1 && g[i].size() < 3) {
                        puts("NO");
                        return 0;
                }
        }
        int root = -1;
        rep(i, n) {
                if (g[i].size() != 1) {
                        root = i;
                        break;
                }
        }
        if (root == -1) {
                printf("YES\n1\n1 2 %d\n", g[0][0].second);
                return 0;
        }
        vector<pair<pair<int, int>, int>> res;
        function<void (int, int)> dfs = [&](int u, int prev) {
                for (auto e : g[u]) {
                        int v = e.first;
                        if (v == prev) continue;
                        int val = e.second;
                        function<int (int, int)> gl = [&](int u, int prev) {
                                if (g[u].size() == 1) return u;
                                for (auto e : g[u]) {
                                        int v = e.first;
                                        if (v == prev) continue;
                                        return gl(v, u);
                                }
                                return 0;
                        };

                        vector<int> ul;
                        for (auto e : g[u]) {
                                int vv = e.first;
                                if (vv == v) continue;
                                int l = gl(vv, u);
                                ul.push_back(l);
                                if (ul.size() == 2) break;
                        }

                        if (g[v].size() == 1) {
                                res.push_back({{ul[0], v}, val / 2});
                                res.push_back({{ul[1], v}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                        } else {
                                vector<int> bl;
                                for (auto e : g[v]) {
                                        int vv = e.first;
                                        if (vv == u) continue;
                                        int l = gl(vv, v);
                                        bl.push_back(l);
                                        if (bl.size() == 2) break;
                                }
                                res.push_back({{ul[0], bl[0]}, val / 2});
                                res.push_back({{ul[1], bl[1]}, val / 2});
                                res.push_back({{ul[0], ul[1]}, - val / 2});
                                res.push_back({{bl[0], bl[1]}, - val / 2});
                        }

                        dfs(v, u);
                }
        };
        dfs(root, -1);
        map<pair<int, int>, long long> ans;
        rep(i, res.size()) {
                int a = res[i].first.first;
                int b = res[i].first.second;
                ans[make_pair(min(a, b), max(a, b))] += res[i].second;
        }
        printf("YES\n%d\n", (int) ans.size());
        for (auto a : ans) {
                printf("%d %d %lld\n", a.first.first + 1, a.first.second + 1, a.second);
        }
        return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define lld long double
#define MOD 1000000007
#define CAP 10000000
#define inf 1000000000000000000LL
#define pii pair<ll,ll>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define endl '\n'
#define sz(v) v.size()
#define all(v)    v.begin(),v.end()
#define fast  ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
using namespace std;
ll power(ll x,ll y, ll md=MOD){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x = (x*x)%md;y = y>>1;}return res%md;}
#define dbg(x) cout <<#x<<":"<<x<<endl;

#define int ll

ll min1() {return inf;}
ll max1() {return -inf;}

template<typename... Args>
int min1(int a, Args... args) {return min(a,min1(args...));}
template<typename... Args>
int max1(int a, Args... args) {return max(a,max1(args...));}

struct node {
	std::vector<ll> v,w;
} nodes1[1002], nodes[1002];

ll n;
std::vector<pair<pii,ll> > fin; //final ans

ll f = 1;

pair<pii,pii> dfs(ll parent, ll index, ll prev){

	if(!f) return mp(mp(0,0),mp(0,0));

	ll len = nodes[index].v.size();
	if(len==0) return mp(mp(index,prev),mp(-inf,0));

	pair<pii,pii> t1,t2,t3;
	for(int i=0;i<1;i++){
		t2 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
	}

	for(int i=1;i<len;i++){
		t3 = t1;

		t1 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
		fin.pb(mp(mp(t1.f.f,t2.f.f),t1.f.s));
		t2.f.s -= t1.f.s;
		t1.f.s = 0;

		if(t1.s.f!=-inf){
			fin.pb(mp(mp(t1.s.f,t2.f.f),t1.s.s));
			t2.f.s -= t1.s.s;
			t1.s.s = 0;
		}
	}

	if(t2.f.s + t2.s.s == prev) return t2;

	if(len==1) {
		if(parent==-1){
			fin.pb(mp(mp(t2.f.f,index),t2.f.s));
			if(t2.s.f!=-inf) fin.pb(mp(mp(t2.s.f,index),t2.s.s));
			return t2;
		}
		f=0;
		return t2;
	}

	if(t2.s.s!=0){
		fin.pb(mp(mp(t1.f.f,t2.s.f),t2.s.s));
		t1.f.s -= t2.s.s;
		t2.s.s = 0;
	}

	ll diff = prev - (t2.f.s+t2.s.s+t1.f.s);
	assert(diff%2==0);
	diff/=2;

	fin.pb(mp(mp(t1.f.f,t2.f.f),-diff));
	t1.f.s += diff;
	t2.f.s += diff;

	if(parent==-1){
		if(len==2&&diff) f=0;

		if(diff){
			fin.pb(mp(mp(t3.f.f,t1.f.f),t1.f.s));
			fin.pb(mp(mp(t3.f.f,t2.f.f),t2.f.s));
		}
		return t2;
	}

	return mp(mp(t1.f.f,t1.f.s),mp(t2.f.f,t2.f.s));

}

void dfs1(ll parent, ll index){
	ll len = nodes1[index].v.size();
	for(int i=0;i<len;i++){
		if(nodes1[index].v[i]!=parent){
			dfs1(index, nodes1[index].v[i]);
			nodes[index].v.pb(nodes1[index].v[i]);
			nodes[index].w.pb(nodes1[index].w[i]);
		}
	}
}

signed main() {
	fast;

	cin>>n;

	for(int i=0;i<n-1;i++){
		ll u,v,val;
		cin>>u>>v>>val;
		nodes1[v].v.pb(u);
		nodes1[v].w.pb(val);
		nodes1[u].v.pb(v);
		nodes1[u].w.pb(val);
	}

	dfs1(-1,1);

	dfs(-1,1,0);

	if(!f) {
		cout<<"NO";
		return 0;
	}

	cout<<"YES\n";
	cout<<fin.size()<<endl;
	for(auto ans: fin) cout<<ans.f.f<<" "<<ans.f.s<<" "<<ans.s<<endl;
}


#include <bits/stdc++.h>
#define ll long long
#define lld long double
#define MOD 1000000007
#define CAP 10000000
#define inf 1000000000000000000LL
#define pii pair<ll,ll>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define endl '\n'
#define sz(v) v.size()
#define all(v)    v.begin(),v.end()
#define fast  ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
using namespace std;
ll power(ll x,ll y, ll md=MOD){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x = (x*x)%md;y = y>>1;}return res%md;}
#define dbg(x) cout <<#x<<":"<<x<<endl;

#define int ll

ll min1() {return inf;}
ll max1() {return -inf;}

template<typename... Args>
int min1(int a, Args... args) {return min(a,min1(args...));}
template<typename... Args>
int max1(int a, Args... args) {return max(a,max1(args...));}

struct node {
	std::vector<ll> v,w;
} nodes1[1002], nodes[1002];

ll n;
std::vector<pair<pii,ll> > fin; //final ans

ll f = 1;

pair<pii,pii> dfs(ll parent, ll index, ll prev){

	if(!f) return mp(mp(0,0),mp(0,0));

	ll len = nodes[index].v.size();
	if(len==0) return mp(mp(index,prev),mp(-inf,0));

	pair<pii,pii> t1,t2,t3;
	for(int i=0;i<1;i++){
		t2 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
	}

	for(int i=1;i<len;i++){
		t3 = t1;

		t1 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
		fin.pb(mp(mp(t1.f.f,t2.f.f),t1.f.s));
		t2.f.s -= t1.f.s;
		t1.f.s = 0;

		if(t1.s.f!=-inf){
			fin.pb(mp(mp(t1.s.f,t2.f.f),t1.s.s));
			t2.f.s -= t1.s.s;
			t1.s.s = 0;
		}
	}

	if(t2.f.s + t2.s.s == prev) return t2;

	if(len==1) {
		if(parent==-1){
			fin.pb(mp(mp(t2.f.f,index),t2.f.s));
			if(t2.s.f!=-inf) fin.pb(mp(mp(t2.s.f,index),t2.s.s));
			return t2;
		}
		f=0;
		return t2;
	}

	if(t2.s.s!=0){
		fin.pb(mp(mp(t1.f.f,t2.s.f),t2.s.s));
		t1.f.s -= t2.s.s;
		t2.s.s = 0;
	}

	ll diff = prev - (t2.f.s+t2.s.s+t1.f.s);
	assert(diff%2==0);
	diff/=2;

	fin.pb(mp(mp(t1.f.f,t2.f.f),-diff));
	t1.f.s += diff;
	t2.f.s += diff;

	if(parent==-1){
		if(len==2&&diff) f=0;

		if(!diff){
			fin.pb(mp(mp(t3.f.f,t1.f.f),t1.f.s));
			fin.pb(mp(mp(t3.f.f,t2.f.f),t2.f.s));
		}
		return t2;
	}

	return mp(mp(t1.f.f,t1.f.s),mp(t2.f.f,t2.f.s));

}

void dfs1(ll parent, ll index){
	ll len = nodes1[index].v.size();
	for(int i=0;i<len;i++){
		if(nodes1[index].v[i]!=parent){
			dfs1(index, nodes1[index].v[i]);
			nodes[index].v.pb(nodes1[index].v[i]);
			nodes[index].w.pb(nodes1[index].w[i]);
		}
	}
}

signed main() {
	fast;

	cin>>n;

	for(int i=0;i<n-1;i++){
		ll u,v,val;
		cin>>u>>v>>val;
		nodes1[v].v.pb(u);
		nodes1[v].w.pb(val);
		nodes1[u].v.pb(v);
		nodes1[u].w.pb(val);
	}

	dfs1(-1,1);

	dfs(-1,1,0);

	if(!f) {
		cout<<"NO";
		return 0;
	}

	cout<<"YES\n";
	cout<<fin.size()<<endl;
	for(auto ans: fin) cout<<ans.f.f<<" "<<ans.f.s<<" "<<ans.s<<endl;
}


#include <bits/stdc++.h>
#define ll long long
#define lld long double
#define MOD 1000000007
#define CAP 10000000
#define inf 1000000000000000000LL
#define pii pair<ll,ll>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define endl '\n'
#define sz(v) v.size()
#define all(v)    v.begin(),v.end()
#define fast  ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
using namespace std;
ll power(ll x,ll y, ll md=MOD){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x = (x*x)%md;y = y>>1;}return res%md;}
#define dbg(x) cout <<#x<<":"<<x<<endl;

#define int ll

ll min1() {return inf;}
ll max1() {return -inf;}

template<typename... Args>
int min1(int a, Args... args) {return min(a,min1(args...));}
template<typename... Args>
int max1(int a, Args... args) {return max(a,max1(args...));}

struct node
{
	std::vector<ll> v,w;
} nodes1[1002], nodes[1002];

ll n;

std::vector<pair<pii,ll> > fin;

ll f = 1;

pair<pii,pii> dfs(ll parent, ll index, ll prev){

	if(!f) return mp(mp(0,0),mp(0,0));

	//cout<<"#"<<index<<endl;
	ll len = nodes[index].v.size();
	if(len==0) return mp(mp(index,prev),mp(-inf,0));

	ll ss = 0;

	pair<pii,pii> t2,t1,t3;
	for(int i=0;i<1;i++){
		t2 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
	}

	for(int i=1;i<len;i++){
		t3 = t1;

		t1 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
		fin.pb(mp(mp(t1.f.f,t2.f.f),t1.f.s));
		t2.f.s -= t1.f.s;
		t1.f.s = 0;

		if(t1.s.f!=-inf){
			fin.pb(mp(mp(t1.s.f,t2.f.f),t1.s.s));
			t2.f.s -= t1.s.s;
			t1.s.s = 0;
		}

	}

	if(t2.f.s+t2.s.s == prev) return t2;

	if(len==1) {f=0;return t2;}

	ll diff = prev - t2.f.s+t2.s.s;
	assert(diff%2==0);
	diff/=2;

	if(t2.s.s!=0){
		fin.pb(mp(mp(t1.f.f,t2.s.f),t2.s.s));
		t1.f.s -= t2.s.s;
		t2.s.s = 0;
	}

	diff = prev - (t2.f.s+t2.s.s+t1.f.s);
	assert(diff%2==0);
	diff/=2;

	fin.pb(mp(mp(t1.f.f,t2.f.f),-diff));
	t1.f.s += diff;
	t2.f.s += diff;

	if(parent==-1){
		if(len==2&&diff) f=0;
		if(!diff) return t2;

		fin.pb(mp(mp(t3.f.f,t1.f.f),t1.f.s));
		fin.pb(mp(mp(t3.f.f,t2.f.f),t2.f.s));

		return t2;
	}

	return mp(mp(t1.f.f,t1.f.s),mp(t2.f.f,t2.f.s));

}

void dfs1(ll parent, ll index){
	ll len = nodes1[index].v.size();
	for(int i=0;i<len;i++){
		if(nodes1[index].v[i]!=parent){
			dfs1(index, nodes1[index].v[i]);
			nodes[index].v.pb(nodes1[index].v[i]);
			nodes[index].w.pb(nodes1[index].w[i]);
		}
	}
}

signed main() {
	fast;

	cin>>n;

	for(int i=0;i<n-1;i++){
		ll u,v,val;
		cin>>u>>v>>val;
		u--;
		v--;
		nodes1[v].v.pb(u);
		nodes1[v].w.pb(val);
		nodes1[u].v.pb(v);
		nodes1[u].w.pb(val);
	}

	dfs1(-1,0);

	dfs(-1,0,0);

	if(!f) {
		cout<<"NO";
		return 0;
	}

	cout<<"YES\n";

	cout<<fin.size()<<endl;

	for(int i=0;i<fin.size();i++) cout<<fin[i].f.f+1<<" "<<fin[i].f.s+1<<" "<<fin[i].s<<endl;

}


#include <bits/stdc++.h>
#define ll long long
#define lld long double
#define MOD 1000000007
#define CAP 10000000
#define inf 1000000000000000000LL
#define pii pair<ll,ll>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define endl '\n'
#define sz(v) v.size()
#define all(v)    v.begin(),v.end()
#define fast  ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
using namespace std;
ll power(ll x,ll y, ll md=MOD){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x = (x*x)%md;y = y>>1;}return res%md;}
#define dbg(x) cout <<#x<<":"<<x<<endl;

#define int ll

ll min1() {return inf;}
ll max1() {return -inf;}

template<typename... Args>
int min1(int a, Args... args) {return min(a,min1(args...));}
template<typename... Args>
int max1(int a, Args... args) {return max(a,max1(args...));}

struct node
{
	std::vector<ll> v,w;
} nodes1[1002], nodes[1002];

ll n;

std::vector<pair<pii,ll> > fin;

ll f = 1;

pair<pii,pii> dfs(ll parent, ll index, ll prev){

	if(!f) return mp(mp(0,0),mp(0,0));

	//cout<<"#"<<index<<endl;
	ll len = nodes[index].v.size();
	if(len==0) return mp(mp(index,prev),mp(-inf,0));

	ll ss = 0;

	pair<pii,pii> t2,t1,t3;
	for(int i=0;i<1;i++){
		t2 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
	}

	for(int i=1;i<len;i++){
		t3 = t1;

		t1 = dfs(index, nodes[index].v[i], nodes[index].w[i]);
		fin.pb(mp(mp(t1.f.f,t2.f.f),t1.f.s));
		t2.f.s -= t1.f.s;
		t1.f.s = 0;

		if(t1.s.f!=-inf){
			fin.pb(mp(mp(t1.s.f,t2.f.f),t1.s.s));
			t2.f.s -= t1.s.s;
			t1.s.s = 0;
		}

	}

	if(t2.f.s + t2.s.s == prev) return t2;

	if(len==1) {
		if(parent==-1){
			fin.pb(mp(mp(t2.f.f,index),t2.f.s));
			if(t2.s.f!=-inf) fin.pb(mp(mp(t2.s.f,index),t2.s.s));
			return t2;
		}
		f=0;
		return t2;
	}

	ll diff = prev - t2.f.s+t2.s.s;
	assert(diff%2==0);
	diff/=2;

	if(t2.s.s!=0){
		fin.pb(mp(mp(t1.f.f,t2.s.f),t2.s.s));
		t1.f.s -= t2.s.s;
		t2.s.s = 0;
	}

	diff = prev - (t2.f.s+t2.s.s+t1.f.s);
	assert(diff%2==0);
	diff/=2;

	fin.pb(mp(mp(t1.f.f,t2.f.f),-diff));
	t1.f.s += diff;
	t2.f.s += diff;

	if(parent==-1){
		if(len==2&&diff) f=0;
		if(!diff) return t2;

		fin.pb(mp(mp(t3.f.f,t1.f.f),t1.f.s));
		fin.pb(mp(mp(t3.f.f,t2.f.f),t2.f.s));

		return t2;
	}

	return mp(mp(t1.f.f,t1.f.s),mp(t2.f.f,t2.f.s));

}

void dfs1(ll parent, ll index){
	ll len = nodes1[index].v.size();
	for(int i=0;i<len;i++){
		if(nodes1[index].v[i]!=parent){
			dfs1(index, nodes1[index].v[i]);
			nodes[index].v.pb(nodes1[index].v[i]);
			nodes[index].w.pb(nodes1[index].w[i]);
		}
	}
}

signed main() {
	fast;

	cin>>n;

	for(int i=0;i<n-1;i++){
		ll u,v,val;
		cin>>u>>v>>val;
		u--;
		v--;
		nodes1[v].v.pb(u);
		nodes1[v].w.pb(val);
		nodes1[u].v.pb(v);
		nodes1[u].w.pb(val);
	}

	dfs1(-1,0);

	dfs(-1,0,0);

	if(!f) {
		cout<<"NO";
		return 0;
	}

	cout<<"YES\n";

	cout<<fin.size()<<endl;

	for(int i=0;i<fin.size();i++) cout<<fin[i].f.f+1<<" "<<fin[i].f.s+1<<" "<<fin[i].s<<endl;

}


//check pp
#include <bits/stdc++.h>
#define IO_OP std::ios::sync_with_stdio(0); std::cin.tie(0);
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define EB emplace_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pi;
typedef vector<int> vi;

const int INF = 1e9 + 7;

vi G[1024];
vector<pair<pi, int>> e, ans, out;

int dfs(int u, int p) {
	for(int v:G[u])
		if(v != p)
			return dfs(v, u);
	return u;
}

int main()
{
	IO_OP;

	int n;
	cin >> n;
	for(int i=0;i<n-1;i++) {
		int u, v, val;
		cin >> u >> v >> val;
		G[u].PB(v);
		G[v].PB(u);
		e.PB({{u, v}, val/2});
	}
	for(int i=1;i<=n;i++) {
		if(G[i].size() == 2) {
			cout << "NO" << endl;
			return 0;
		}
	}
	cout << "YES" << endl;
	for(auto p:e) {
		int u = p.F.F, v = p.F.S, val = p.S;
		vi x, y;
		for(int w:G[u]) {
			if(x.size() == 2) break;
			if(w != v) x.PB(w);
		}
		for(int w:G[v]) {
			if(y.size() == 2) break;
			if(w != u) y.PB(w);
		}
		int a, b, c, d;
		a = b = u, c = d = v;
		if(x.size()) a = dfs(x[0], u), b = dfs(x[1], u);
		if(y.size()) c = dfs(y[0], v), d = dfs(y[1], v);

		ans.PB({{a, c}, val});
		ans.PB({{b, d}, val});
		ans.PB({{a, b}, -val});
		ans.PB({{c, d}, -val});
	}
	for(auto p:ans) {
		if(p.F.F != p.F.S)
			out.PB(p);
	}
	cout << out.size() << endl;
	for(auto p:out)
		cout << p.F.F << " " << p.F.S << " " << p.S << endl;

}


#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define file(x)freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define rt register int
#define l putchar('\n')
#define ll long long
#define r read()
using namespace std;
inline ll read(){
    ll x=0;char zf=1;char ch=getchar();
    while(ch!='-'&&!isdigit(ch))ch=getchar();
    if(ch=='-')zf=-1,ch=getchar();
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
}
void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt;
int d[1010];
struct ed{
	int x,y,v;
}a[1010],ans[10010];
vector<int>e[1010];
void push(int x,int y,int z){
	ans[++cnt]={x,y,z};
}
pair<int,int>get(int x,int pre){
	if(d[x]==1)return {x,0};
	pair<int,int>ret={0,0};
	for(auto i:e[x])if(i!=pre){
		if(ret.first==0)ret.first=get(i,x).first;
		else ret.second=get(i,x).first;
	}
	return ret;
}
int main(){
	n=r;
	for(rt i=1;i<n;i++){
		x=r;y=r;z=r;d[x]++;d[y]++;
		a[i]={x,y,z};
		e[x].push_back(y);
		e[y].push_back(x);
	}
	for(rt i=1;i<=n;i++)if(d[i]==2){
		cout<<"NO";return 0;
	}
	puts("YES");
	for(rt i=1;i<n;i++){
		if(d[a[i].x]>d[a[i].y])swap(a[i].x,a[i].y);
		if(d[a[i].x]==1&&d[a[i].y]==1){
			push(a[i].x,a[i].y,a[i].v);
		}
		else
		if(d[a[i].x]==1){
			pair<int,int>now=get(a[i].y,a[i].x);
			push(a[i].x,now.first,a[i].v/2);
			push(a[i].x,now.second,a[i].v/2);
			push(now.first,now.second,-a[i].v/2);
		}
		else{
			pair<int,int>n1=get(a[i].x,a[i].y),n2=get(a[i].y,a[i].x);
			int v=a[i].v/2;
			push(n1.first,n2.first,v);
			push(n1.second,n2.second,v);
			push(n1.first,n1.second,-v);
			push(n2.first,n2.second,-v);
		}
	}
	writeln(cnt);
	for(rt i=1;i<=cnt;i++)cout<<ans[i].x<<' '<<ans[i].y<<' '<<ans[i].v<<endl;
	return 0;
}


#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define file(x)freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define rt register int
#define l putchar('\n')
#define ll long long
#define r read()
using namespace std;
inline ll read(){
    ll x=0;char zf=1;char ch=getchar();
    while(ch!='-'&&!isdigit(ch))ch=getchar();
    if(ch=='-')zf=-1,ch=getchar();
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
}
void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt;
int d[1010];
struct ed{
	int x,y,v;
}a[1010],ans[10010];
vector<int>e[1010];
void push(int x,int y,int z){
	ans[++cnt]={x,y,z};
}
pair<int,int>get(int x,int pre){
	if(d[x]==1)return {x,0};
	pair<int,int>ret={0,0};
	for(auto i:e[x])if(i!=pre){
		if(ret.first==0)ret.first=get(i,x).first;
		else ret.second=get(i,x).first;
	}
	return ret;
}
int main(){
	n=r;
	for(rt i=1;i<n;i++){
		x=r;y=r;z=r;d[x]++;d[y]++;
		a[i]={x,y,z};
		e[x].push_back(y);
		e[y].push_back(x);
	}
	for(rt i=1;i<=n;i++)if(d[i]==2){
		cout<<"NO";return 0;
	}
	puts("YES");
	for(rt i=1;i<n;i++){
		if(d[a[i].x]>d[a[i].y])swap(a[i].x,a[i].y);
		if(d[a[i].x]==1&&d[a[i].y]==1){
			push(a[i].x,a[i].y,a[i].v);
		}
		else
		if(d[a[i].x]==1){
			pair<int,int>now=get(a[i].y,a[i].x);
			push(a[i].x,now.first,a[i].v/2);
			push(a[i].x,now.second,a[i].v/2);
			push(now.first,now.second,-a[i].v/2);
		}
		else{
			pair<int,int>n1=get(a[i].x,a[i].y),n2=get(a[i].x,a[i].y);
			int v=a[i].v/2;
			push(n1.first,n2.first,v);
			push(n1.second,n2.second,v);
			push(n1.first,n2.first,-v);
			push(n1.second,n2.second,-v);
		}
	}
	writeln(cnt);
	for(rt i=1;i<=cnt;i++)cout<<ans[i].x<<' '<<ans[i].y<<' '<<ans[i].v<<endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 10007
#define oo 2000000007
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=x;LoOpEr-->0;)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n;
vector< vector<int> > adj;
vector<int> par;
vector<int> leaf;
struct edge{
    int u,v,w;
};
vector<edge> E;

void data()
{
    adj.resize(n+1);
    par.resize(n+1);
    leaf.resize(n+1);
    E.resize(n-1);
}

void dfs(const int &u,const int &parent)
{
    par[u]=parent;

    if(adj[u].size()==2)
    {
        cout<<"NO";
        exit(0);
    }
    if(parent && adj[u].size()==1)
    {
        leaf[u]=u;
        return;
    }

    for(const int &v: adj[u])
        if(v!=parent)
            dfs(v,u),leaf[u]=leaf[v];
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    data();
    #define add_edge(e) adj[e.u].push_back(e.v),adj[e.v].push_back(e.u)
    for(int i=0;i<n-1;i++) cin>>E[i].u>>E[i].v>>E[i].w,add_edge(E[i]);

    int root=-1;
    for(int i=1;i<=n;i++)
        if(adj[i].size()==1)
        {
            dfs(root=i,0);
            break;
        }

    for(int i=1;i<=n;i++) cerr<<i<<" : "<<leaf[i]<<"\n";cerr<<"\n";

    cout<<"YES\n";
    for(const edge &e: E)
    {
        int u=e.u,v=e.v,w=e.w;

        if(u!=par[v]) swap(u,v);

        if(adj[u].size()==1 || adj[v].size()==1)
        {
            cout<<u<<" "<<v<<" "<<w<<"\n";
            continue;
        }

        int l1,l2;

        if(adj[u][0]!=v && leaf[adj[u][0]]!=leaf[u]) l1=leaf[adj[u][0]];
        else if(adj[u][0]!=v && leaf[adj[u][1]]!=leaf[u]) l1=leaf[adj[u][1]];
        else l1=leaf[adj[1][2]];

        if(adj[v][0]!=u && leaf[adj[v][0]]!=leaf[v]) l2=leaf[adj[v][0]];
        else if(adj[v][1]!=u && leaf[adj[v][1]]!=leaf[v]) l2=leaf[adj[v][1]];
        else l2=leaf[adj[v][2]];

        cout<<root<<" "<<leaf[v]<<" "<<w/2<<"\n";
        cout<<l1<<" "<<l2<<" "<<w/2<<"\n";
        cout<<root<<" "<<l1<<" "<<-w/2<<"\n";
        cout<<leaf[v]<<" "<<l2<<" "<<-w/2<<"\n";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 10007
#define oo 2000000007
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=x;LoOpEr-->0;)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n;
vector< vector<int> > adj;
vector<int> par;
vector<int> leaf;
struct edge{
    int u,v,w;
};
vector<edge> E;

void data()
{
    adj.resize(n+1);
    par.resize(n+1);
    leaf.resize(n+1);
    E.resize(n-1);
}

void dfs(const int &u,const int &parent)
{
    par[u]=parent;

    if(adj[u].size()==2)
    {
        cout<<"NO";
        exit(0);
    }
    if(parent && adj[u].size()==1)
    {
        leaf[u]=u;
        return;
    }

    for(const int &v: adj[u])
        if(v!=parent)
            dfs(v,u),leaf[u]=leaf[v];
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    data();
    #define add_edge(e) adj[e.u].push_back(e.v),adj[e.v].push_back(e.u)
    for(int i=0;i<n-1;i++) cin>>E[i].u>>E[i].v>>E[i].w,add_edge(E[i]);

    int root=-1;
    for(int i=1;i<=n;i++)
        if(adj[i].size()==1)
        {
            dfs(root=i,0);
            break;
        }

    for(int i=1;i<=n;i++) cerr<<i<<" : "<<leaf[i]<<"\n";cerr<<"\n";

    for(const edge &e: E)
    {
        int u=e.u,v=e.v,w=e.w;

        if(u!=par[v]) swap(u,v);

        if(adj[u].size()==1 || adj[v].size()==1)
        {
            cout<<u<<" "<<v<<" "<<w<<"\n";
            continue;
        }

        int l1,l2;

        if(adj[u][0]!=v && leaf[adj[u][0]]!=leaf[u]) l1=leaf[adj[u][0]];
        else if(adj[u][0]!=v && leaf[adj[u][1]]!=leaf[u]) l1=leaf[adj[u][1]];
        else l1=leaf[adj[1][2]];

        if(adj[v][0]!=u && leaf[adj[v][0]]!=leaf[v]) l2=leaf[adj[v][0]];
        else if(adj[v][1]!=u && leaf[adj[v][1]]!=leaf[v]) l2=leaf[adj[v][1]];
        else l2=leaf[adj[v][2]];

        cout<<root<<" "<<leaf[v]<<" "<<w/2<<"\n";
        cout<<l1<<" "<<l2<<" "<<w/2<<"\n";
        cout<<root<<" "<<l1<<" "<<-w/2<<"\n";
        cout<<leaf[v]<<" "<<l2<<" "<<-w/2<<"\n";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 10007
#define oo 2000000007
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=x;LoOpEr-->0;)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n;
vector< vector<int> > adj;
vector<int> par;
vector<int> leaf;
struct edge{
    int u,v,w;
};
vector<edge> E;

void data()
{
    adj.resize(n+1);
    par.resize(n+1);
    leaf.resize(n+1);
    E.resize(n-1);
}

void dfs(const int &u,const int &parent)
{
    par[u]=parent;

    if(adj[u].size()==2)
    {
        cout<<"NO";
        exit(0);
    }
    if(parent && adj[u].size()==1)
    {
        leaf[u]=u;
        return;
    }

    for(const int &v: adj[u])
        if(v!=parent)
            dfs(v,u),leaf[u]=leaf[v];
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    data();
    #define add_edge(e) adj[e.u].push_back(e.v),adj[e.v].push_back(e.u)
    for(int i=0;i<n-1;i++) cin>>E[i].u>>E[i].v>>E[i].w,add_edge(E[i]);

    int root=-1;
    for(int i=1;i<=n;i++)
        if(adj[i].size()==1)
        {
            dfs(root=i,0);
            break;
        }

    vector<edge> ans;
    for(const edge &e: E)
    {
        int u=e.u,v=e.v,w=e.w;

        if(u!=par[v]) swap(u,v);

        if(adj[u].size()==1 || adj[v].size()==1)
        {
            ans.push_back({u,v,w});
            continue;
        }

        int l1,l2;

        if(adj[u][0]!=v && leaf[adj[u][0]]!=leaf[u]) l1=leaf[adj[u][0]];
        else if(adj[u][0]!=v && leaf[adj[u][1]]!=leaf[u]) l1=leaf[adj[u][1]];
        else l1=leaf[adj[1][2]];

        if(adj[v][0]!=u && leaf[adj[v][0]]!=leaf[v]) l2=leaf[adj[v][0]];
        else if(adj[v][1]!=u && leaf[adj[v][1]]!=leaf[v]) l2=leaf[adj[v][1]];
        else l2=leaf[adj[v][2]];

        ans.push_back({root,leaf[v],w/2});
        ans.push_back({l1,l2,w/2});
        ans.push_back({root,l1,-w/2});
        ans.push_back({leaf[v],l2,-w/2});
    }

    cout<<"YES\n";
    cout<<ans.size()<<"\n";

    for(const edge &e: ans)
        cout<<e.u<<" "<<e.v<<" "<<e.w<<"\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 10007
#define oo 2000000007
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=x;LoOpEr-->0;)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n;
vector< vector<int> > adj;
vector<int> par;
vector<int> leaf;
struct edge{
    int u,v,w;
};
vector<edge> E;

void data()
{
    adj.resize(n+1);
    par.resize(n+1);
    leaf.resize(n+1);
    E.resize(n-1);
}

void dfs(const int &u,const int &parent)
{
    par[u]=parent;

    if(adj[u].size()==2)
    {
        cout<<"NO";
        exit(0);
    }
    if(parent && adj[u].size()==1)
    {
        leaf[u]=u;
        return;
    }

    for(const int &v: adj[u])
        if(v!=parent)
            dfs(v,u),leaf[u]=leaf[v];
}

int leafdad(const int &u,const int &v)
{
    if(adj[u][0]!=v && adj[u][0]!=par[u]) return leaf[adj[u][0]];
    else if(adj[u][1]!=v && adj[u][1]!=par[u]) return leaf[adj[u][1]];
    else return leaf[adj[u][2]];
}
int leafson(const int &v,const int &u)
{
    if(adj[v][0]!=u && leaf[adj[v][0]]!=leaf[v]) return leaf[adj[v][0]];
    else if(adj[v][1]!=u && leaf[adj[v][1]]!=leaf[v]) return leaf[adj[v][1]];
    else return leaf[adj[v][2]];
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    data();
    #define add_edge(e) adj[e.u].push_back(e.v),adj[e.v].push_back(e.u)
    for(int i=0;i<n-1;i++) cin>>E[i].u>>E[i].v>>E[i].w,add_edge(E[i]);

    int root=-1;
    for(int i=1;i<=n;i++)
        if(adj[i].size()==1)
        {
            dfs(root=i,0);
            break;
        }

    vector<edge> ans;
    for(const edge &e: E)
    {
        int u=e.u,v=e.v,w=e.w;
        int l1,l2;

        if(adj[u].size()==1 || adj[v].size()==1)
        {
            if(adj[u].size()==1) swap(u,v);

            if(adj[u].size()==1 && adj[v].size()==1) ans.push_back({u,v,w});
            else if(u==par[v])
            {
                l1=leafdad(u,v);
                ans.push_back({root,v,w/2}),ans.push_back({l1,v,w/2}),ans.push_back({root,l1,-w/2});
            }
            else
            {
                l1=leafson(u,v);
                ans.push_back({leaf[u],v,w/2}),ans.push_back({l1,v,w/2}),ans.push_back({leaf[u],l1,-w/2});
            }

            continue;
        }

        if(u!=par[v]) swap(u,v);
        l1=leafdad(u,v);
        l2=leafson(v,u);
        ans.push_back({root,leaf[v],w/2});
        ans.push_back({l1,l2,w/2});
        ans.push_back({root,l1,-w/2});
        ans.push_back({leaf[v],l2,-w/2});
    }

    cout<<"YES\n";
    cout<<ans.size()<<"\n";

    for(const edge &e: ans)
        cout<<e.u<<" "<<e.v<<" "<<e.w<<"\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 10007
#define oo 2000000007
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=x;LoOpEr-->0;)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n;
vector< vector<int> > adj;
vector<int> par;
vector<int> leaf;
struct edge{
    int u,v,w;
};
vector<edge> E;

void data()
{
    adj.resize(n+1);
    par.resize(n+1);
    leaf.resize(n+1);
    E.resize(n-1);
}

void dfs(const int &u,const int &parent)
{
    par[u]=parent;

    if(adj[u].size()==2)
    {
        cout<<"NO";
        exit(0);
    }
    if(parent && adj[u].size()==1)
    {
        leaf[u]=u;
        return;
    }

    for(const int &v: adj[u])
        if(v!=parent)
            dfs(v,u),leaf[u]=leaf[v];
}

int findleaf(const int &u,const int &v)
{
    if(adj[u][0]!=v && leaf[adj[u][0]]!=leaf[u]) return leaf[adj[u][0]];
    else if(adj[u][0]!=v && leaf[adj[u][1]]!=leaf[u]) return leaf[adj[u][1]];
    else return leaf[adj[1][2]];
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    data();
    #define add_edge(e) adj[e.u].push_back(e.v),adj[e.v].push_back(e.u)
    for(int i=0;i<n-1;i++) cin>>E[i].u>>E[i].v>>E[i].w,add_edge(E[i]);

    int root=-1;
    for(int i=1;i<=n;i++)
        if(adj[i].size()==1)
        {
            dfs(root=i,0);
            break;
        }

    vector<edge> ans;
    for(const edge &e: E)
    {
        int u=e.u,v=e.v,w=e.w;
        int l1,l2;

        if(u!=par[v]) swap(u,v);

        if(adj[u].size()==1 || adj[v].size()==1)
        {
            if(adj[u].size()==1 && adj[v].size()==1) ans.push_back({u,v,w});
            else l1=findleaf(u,v),
                ans.push_back({root,v,w/2}),
                ans.push_back({l1,v,w/2}),
                ans.push_back({root,l1,-w/2});

            continue;
        }

        l1=findleaf(u,v);
        l2=findleaf(v,u);
        ans.push_back({root,leaf[v],w/2});
        ans.push_back({l1,l2,w/2});
        ans.push_back({root,l1,-w/2});
        ans.push_back({leaf[v],l2,-w/2});
    }

    cout<<"YES\n";
    cout<<ans.size()<<"\n";

    for(const edge &e: ans)
        cout<<e.u<<" "<<e.v<<" "<<e.w<<"\n";
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int power(int a, int b)
{
    int rep = 1;
    while(b--)
    {
        rep *= a;
    }
    return rep;
}
int main()
{
    int n, a;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &a);
        int i = a, n = 0, k = 0;
        while(i > 0)
        {
            n++;
            if(i % 10 != 0) k++;
            i /= 10;
        }
        printf("%d\n", k);
        for(int l = 0; l < n; l++)
        {
            i = a % 10;
            if(i != 0)
            {
                printf("%d", i*power(10, l));
                if(l != n - 1) printf(" ");
            }
            a /= 10;
        }
        printf("\n");

    }
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main()
{
    int n, a;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &a);
        int i = a, n = 0, k = 0;
        while(i > 0)
        {
            n++;
            if(i % 10 != 0) k++;
            i /= 10;
        }
        printf("%d\n", k);
        for(int l = 0; l < n; l++)
        {
            i = a % 10;
            if(i != 0) printf("%d ", i*((int)(pow(10, l))));
            a /= 10;
        }
        printf("\n");

    }
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main()
{
    int n, a;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &a);
        int i = a, n = 0, k = 0;
        while(i > 0)
        {
            n++;
            if(i % 10 != 0) k++;
            i /= 10;
        }
        printf("%d\n", k);
        for(int l = 0; l < n; l++)
        {
            i = a % 10;
            if(i != 0) printf("%d", i*((int)(pow(10, l))));
            if(l != n - 1 && i != 0) printf(" ");
            a /= 10;
        }
        printf("\n");

    }
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main()
{
    int n, a;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &a);
        int i = a, n = 0, k = 0;
        while(i > 0)
        {
            n++;
            if(i % 10 != 0) k++;
            i /= 10;
        }
        n--;
        printf("%d\n", k);
        while(n >= 0)
        {
            i = (a/((int)(pow(10, n))))*(int)(pow(10, n));
            if(i != 0)
            {
                printf("%d ", i);
            }
            if(n == 0) printf("\n");
            a -= i;
            n--;
        }

    }
	return 0;
}


#include<stdio.h>

int main()
{
    int t;
    scanf("%d",&t);
    for(int i=0;i<t;i++)
    {
        int n;
        int k=1;
        int j=0;
        int a[1000]={0};
        int count=0;
        scanf("%d",&n);

        if(n%10==0)
        {
            count=1;
            a[0]=n;
        }
        else
        {
            while(n%10!=0)
            {
                count++;
                a[j]=(n%10)*k;

            }
            k=k*10;
            n=n/10;
        }

        printf("%d\n",count);
        for(int l=0;l<count;l++)
        {
            printf("%d ",a[l]);
        }

    }
}


#include<stdio.h>

int main()
{
    int t;
    scanf("%d",&t);
    for(int i=0;i<t;i++)
    {
        int n;
        int k=1;
        int j=0;
        int a[1000]={0};
        int count=0;
        scanf("%d",&n);

        if(n%10==0)
        {
            count=1;
            a[0]=n;
        }
        else
        {
            while(n%10!=0)
            {
                count++;
                a[j]=(n%10)*k;
                k=k*10;
                n=n/10;
                j++;
        }

            }

        printf("%d\n",count);
        for(int l=0;l<count;l++)
        {
            printf("%d ",a[l]);
        }

    }
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int arr[5];
        scanf("%d",&n);
        int i = 0;
        int j = 0;
        while(n > 0)
        {
            arr[i] = (n%10)*pow(10,j);
            i++;
            j++;
            n = n/10;
        }
        int count = 0;
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                count++;
            }
        }
        printf("%d\n",count);
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                printf("%d",&arr[k]);
            }
        }
        printf("\n");
    }
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int arr[5] = {0}
        scanf("%d",&n);
        int i = 0;
        int j = 0;
        while(n > 0)
        {
            arr[i] = (n%10)*pow(10,j);
            i++;
            j++;
            n = n/10;
        }
        int count = 0;
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                count++;
            }
        }
        printf("%d\n",count);
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                printf("%d",arr[k]);
            }
        }
        printf("\n");
    }
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int arr[5] = {0};
        scanf("%d",&n);
        int j = 0;
        while(n > 0)
        {
            arr[j] = (n%10);
            j++;
            n = n/10;
        }
        int count = 0;
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                count++;
            }
        }
        printf("%d\n",count);
        for(int k=0;k<5;k++)
        {
            if(arr[k] != 0)
            {
                printf("%d ",arr[k]*pow(10,k));
            }
        }
        printf("\n");
    }
    return 0;
}