#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        for (auto& x : a) {
            if (x == -1) {
                for (auto& y : b) {
                    if (y != -1) {
                        x = y;
                        y = -1;
                        break;
                    }
                }
            }
        }
        return a;
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int t1 = g[v].getSons()[0].to;
                    int t2 = g[v].getSons()[1].to;
                    if (t1 == u.to) t1 = g[v].getSons()[2].to;
                    if (t2 == u.to) t2 = g[v].getSons()[2].to;

                    int l1 = -1, l2 = -1;
                    for (auto x : leaves[t1]) {
                        if (x == -1) continue;
                        if (x != u.to) {
                            l1 = x;
                        }
                    }
                    for (auto x : leaves[t2]) {
                        if (x == -1) continue;
                        if (x != u.to && x != l1) {
                            l2 = x;
                        }
                    }
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](pii a, pii b) {
        if (a.first != -1 && a.second != -1) {
            return a;
        }
        if (b.first != -1 && b.second != -1) {
            return b;
        }
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        pii rez = {-1, -1};
        bool f = 1;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                rez = mrg(rez, findLeaves2(x.to, v));
            }
        }
        if (f) {
            rez.first = v;
        }
        return rez;
    };
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](const pii& a, const pii& b) {
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        bool f = 1;
        vector<pii> tmp;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                pii cur = findLeaves2(x.to, v);
                if (tmp.size() == 2) continue;
                if (cur.first >= 0 || cur.second >= 0) {
                    tmp.push_back(cur);
                }
            }
        }
        if (tmp.size() == 0) {
            return make_pair(v, -1);
        }
        return mrg(tmp[0], tmp[1]);
    };

    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    if (a.first == -1 || a.second == -1 || b.first == -1 || b.second  == -1) {
                        assert(false);
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    for (int i = 0; i < n; i++) {
        if (g[i].size() >= 3) {
            dfs(i, -1);
            break;
        }
    }

    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        vector<int> t;
        for (auto x : a) t.push_back(x);
        for (auto x : b) t.push_back(x);
        sort(all(t));
        return vector<int>{t[7], t[6], t[5], t[4]};
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1, -1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = leaves[u.to][0];
                    int l2 = leaves[u.to][1];
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](pii a, pii b) {
        if (a.first != -1 && a.second != -1) {
            return a;
        }
        if (b.first != -1 && b.second != -1) {
            return b;
        }
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        pii rez = {-1, -1};
        bool f = 1;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                rez = mrg(rez, findLeaves2(x.to, v));
            }
        }
        if (f) {
            rez.first = v;
        }
        return rez;
    };
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    if (a.first == -1 || a.second == -1 || b.first == -1 || b.second  == -1) {
                        assert(false);
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        for (auto& x : a) {
            if (x == -1) {
                for (auto& y : b) {
                    if (y != -1) {
                        x = y;
                        y = -1;
                        break;
                    }
                }
            }
        }
        return a;
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int t1 = g[v].getSons()[0].to;
                    int t2 = g[v].getSons()[1].to;
                    if (t1 == u.to) t1 = g[v].getSons()[2].to;
                    if (t2 == u.to) t2 = g[v].getSons()[2].to;

                    int l1 = -1, l2 = -1;
                    for (auto x : leaves[t1]) {
                        if (x == -1) continue;
                        if (x != u.to) {
                            l1 = x;
                        }
                    }
                    for (auto x : leaves[t2]) {
                        if (x == -1) continue;
                        if (x != u.to && x != l1) {
                            l2 = x;
                        }
                    }
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        vector<int> t;
        for (auto x : a) t.push_back(x);
        for (auto x : b) t.push_back(x);
        sort(all(t));
        return vector<int>{t[7], t[6], t[5], t[4]};
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1, -1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int t1 = g[v].getSons()[0].to;
                    int t2 = g[v].getSons()[1].to;
                    if (t1 == u.to) t1 = g[v].getSons()[2].to;
                    if (t2 == u.to) t2 = g[v].getSons()[2].to;

                    int l1 = -1, l2 = -1;
                    for (auto x : leaves[t1]) {
                        if (x == -1) continue;
                        if (x != u.to) {
                            l1 = x;
                        }
                    }
                    for (auto x : leaves[t2]) {
                        if (x == -1) continue;
                        if (x != u.to && x != l1) {
                            l2 = x;
                        }
                    }
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    cout << u.to + 1 << endl;
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


6
1 2 6a#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](pii a, pii b) {
        if (a.first != -1 && a.second != -1) {
            return a;
        }
        if (b.first != -1 && b.second != -1) {
            return b;
        }
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        pii rez = {-1, -1};
        bool f = 1;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                rez = mrg(rez, findLeaves2(x.to, v));
            }
        }
        if (f) {
            rez.first = v;
        }
        return rez;
    };
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}

1 3 8
1 4 12
2 5 2
2 6 4


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        for (auto& x : a) {
            if (x == -1) {
                for (auto& y : b) {
                    if (y != -1) {
                        x = y;
                        y = -1;
                        break;
                    }
                }
            }
        }
        return a;
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int t1 = g[v].getSons()[0].to;
                    int t2 = g[v].getSons()[1].to;
                    if (t1 == u.to) t1 = g[v].getSons()[2].to;
                    if (t2 == u.to) t2 = g[v].getSons()[2].to;

                    int l1 = -1, l2 = -1;
                    for (auto x : leaves[t1]) {
                        if (x == -1) continue;
                        if (x != u.to) {
                            l1 = x;
                        }
                    }
                    for (auto x : leaves[t2]) {
                        if (x == -1) continue;
                        if (x != u.to && x != l1) {
                            l2 = x;
                        }
                    }
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        vector<int> t;
        for (auto x : a) t.push_back(x);
        for (auto x : b) t.push_back(x);
        sort(all(t));
        return vector<int>{t[7], t[6], t[5], t[4]};
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1, -1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = leaves[u.to][0];
                    int l2 = leaves[u.to][1];
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l1 + 1, u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        vector<int> t;
        for (auto x : a) t.push_back(x);
        for (auto x : b) t.push_back(x);
        sort(all(t));
        return vector<int>{t[7], t[6], t[5], t[4]};
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1, -1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = leaves[u.to][0];
                    int l2 = leaves[u.to][1];
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }

    vector<vector<int>> leaves(n);

    auto mrg = [&](vector<int> a, vector<int> b) {
        for (auto& x : a) {
            if (x == -1) {
                for (auto& y : b) {
                    if (y != -1) {
                        x = y;
                        y = -1;
                        break;
                    }
                }
            }
        }
        if (*max_element(all(b)) != -1) {
            a[3] = *max_element(all(b));
        }
        return a;
    };

    function<vector<int>(int, int)> preCalc = [&](int v, int p) {
        bool f = 0;
        vector<vector<int>> cur;
        for (const auto& x : g[v].getSons()) {
            if (x.to != p) {
                f = 1;
                cur.push_back(preCalc(x.to, v));
            }
        }
        vector<int> ans = {-1, -1};
        if (!f) {
            ans[0] = v;
        }
        for (auto x : cur) {
            ans = mrg(ans, x);
        }
        return ans;
    };

    for (int i = 0; i < n; i++) {
        leaves[i] = preCalc(i, -1);
    }

    vector<Huita> ans;
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int t1 = g[v].getSons()[0].to;
                    int t2 = g[v].getSons()[1].to;
                    if (t1 == u.to) t1 = g[v].getSons()[2].to;
                    if (t2 == u.to) t2 = g[v].getSons()[2].to;

                    int l1 = -1, l2 = -1;
                    for (auto x : leaves[t1]) {
                        if (x == -1) continue;
                        if (x != u.to) {
                            l1 = x;
                        }
                    }
                    for (auto x : leaves[t2]) {
                        if (x == -1) continue;
                        if (x != u.to && x != l1) {
                            l2 = x;
                        }
                    }
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = {leaves[v][0], leaves[v][1]};
                    pii b = {-1, -1};
                    for (auto x : leaves[u.to]) {
                        if (x == -1) continue;
                        if (a.first != x && a.second != x) {
                            if (b.first == -1) {
                                b.first = x;
                            } else {
                                b.second = x;
                            }
                        }
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](const pii& a, const pii& b) {
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        bool f = 1;
        vector<pii> tmp;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                pii cur = findLeaves2(x.to, v);
                if (tmp.size() == 2) continue;
                if (cur.first >= 0 || cur.second >= 0) {
                    tmp.push_back(cur);
                }
            }
        }
        if (tmp.size() == 0) {
            return make_pair(v, -1);
        }
        return mrg(tmp[0], tmp[1]);
    };

    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else if (g[v].size() == 1) {
                    int l1 = findLeaves(u.to, v, -1);
                    int l2 = findLeaves(l1, -1, v);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    if (a.first == -1 || a.second == -1 || b.first == -1 || b.second  == -1) {
                        assert(false);
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    for (int i = 0; i < n; i++) {
        if (g[i].size() == 1) {
            dfs(i, -1);
            break;
        }
    }

    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
#define itn int
#define all(c) c.begin(),c.end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
using namespace std;

const ll N = 1e6 + 5, inf = 1e18, mod = 1e9 + 7;
const double PI = 3.1415926536;
int days[13] = {0, 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31};

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& mas) {
    for (const auto& x : mas) {
        out << x << ' ';
    }
    out << '\n';
    return out;
}

bool is_prime(ll n) {
    for (ll i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

inline ll getPow(ll a, ll b) {
    ll res = 1ll, tp = a;
    while (b){
        if (b&1ll) {
            res *= tp;
        }
        tp *= tp;
     //   tp %= mod; res %= mod;
        b >>= 1ll;
    }
    return res;
}

ll vec_mult(const pll & t1, const pll & t2, const pll & t3) {
    const ll & x1 = t1.first, y1 = t1.second;
    const ll & x2 = t2.first, y2 = t2.second;
    const ll & x3 = t3.first, y3 = t3.second;
    return abs((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
}

void ok() {
    cout << "YES" << '\n';
}

void no() {
    cout << "NO" << '\n';
}

inline ll nxt() {
    ll x;
    cin >> x;
    return x;
}

struct Edge {
    int to, w;

    Edge(int _to = 0, int _w = 0) :
        to(_to), w(_w) {}
};

struct Node {
    vector<Edge> sons;

    void push(int to, int w) {
        sons.push_back({to, w});
    }
    vector<Edge>& getSons() {
        return sons;
    }

    int size() {
        return sons.size();
    }
};

struct Huita {
    int v, u, w;
    Huita(int _v, int _u, int _w) {
        v = _v;
        u = _u;
        w = _w;
    }
};

ostream& operator<< (ostream& out, const Huita& tmp) {
    out << tmp.v << ' ' << tmp.u << ' ' << tmp.w;
    return out;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n = nxt();
    vector<Node> g(n);
    vector<Edge> buf;
    for (int i = 0; i < n - 1; i++) {
        int v = nxt() - 1, u = nxt() - 1, w = nxt();
        g[v].push(u, w);
        g[u].push(v, w);
    }

    if (n == 2) {
        ok();
        cout << "1\n" << 1 << ' ' << 2 << ' ' << g[0].sons[0].w;
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        if (g[i].size() == 2) {
            no();
            return 0;
        }
    }
    auto mrg = [&](pii a, pii b) {
        return make_pair(max(a.first, a.second), max(b.first, b.second));
    };
    vector<Huita> ans;

    function<int(int, int, int)> findLeaves = [&](int v, int p, int nt) {
        for (auto x : g[v].getSons()) {
            if (x.to != p && x.to != nt) {
                return findLeaves(x.to, v, nt);
            }
        }
        return v;
    };
    function<pii(int, int)> findLeaves2 = [&](int v, int p) {
        pii rez = {-1, -1};
        bool f = 1;
        vector<pii> tmp;
        for (auto x : g[v].getSons()) {
            if (x.to != p) {
                f = 0;
                if (tmp.size() == 2) continue;
                pii cur = findLeaves2(x.to, v);
                if (cur.first >= 0 || cur.second >= 0) {
                    tmp.push_back(cur);
                }
            }
        }
        if (f) {
            rez.first = v;
            return rez;
        }
        return mrg(tmp[0], tmp[1]);
    };
    function<void(int, int)> dfs = [&](int v, int p) {
        for (const auto& u : g[v].getSons()) {
            if (u.to != p) {
                dfs(u.to, v);
                if (g[u.to].size() == 1) {
                    int l1 = findLeaves(v, u.to, -1);
                    int l2 = findLeaves(l1, -1, u.to);
                    ans.push_back({u.to + 1, l1 + 1, u.w / 2});
                    ans.push_back({u.to + 1, l2 + 1, u.w / 2});
                    ans.push_back({l1 + 1, l2 + 1, -u.w / 2});
                } else {
                    pii a = findLeaves2(v, u.to);
                    pii b = findLeaves2(u.to, v);
                    if (a.first == -1 || a.second == -1 || b.first == -1 || b.second  == -1) {
                        assert(false);
                    }
                    ans.push_back({a.first + 1, b.first + 1, u.w / 2});
                    ans.push_back({a.second + 1, b.second + 1, u.w / 2});
                    ans.push_back({a.first + 1, a.second + 1, -u.w / 2});
                    ans.push_back({b.first + 1, b.second + 1, -u.w / 2});
                }
            }
        }
    };
    dfs(0, -1);
    ok();
    cout << ans.size() << '\n';
    for (const auto& x : ans) {
        cout << x << '\n';
    }
    return 0;
}


#include <cstdio>
#include <vector>
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
#define fi first
#define se second
#define pb push_back
const int maxn = 1001;
int n,rt;
vector<pii> adj[maxn];
vector<ppi> ans;
int dfs(int cur,int par,int len) {
    if (adj[cur].size() == 1) return ans.pb({{rt,cur},len}),cur;
    int sum = 0; for (pii nxt : adj[cur]) if (nxt.fi != par) sum += nxt.se;
    int l1 = -1,l2 = -1;
    for (pii nxt : adj[cur]) if (nxt.fi != par) {if (~l1) l2 = dfs(nxt.fi,cur,nxt.se); else l1 = dfs(nxt.fi,cur,nxt.se);}
    ans.pb({{rt,l1},(len-sum)/2}); ans.pb({{rt,l2},(len-sum)/2}); ans.pb({{l1,l2},(sum-len)/2});
    return l1;
}
int main() {
    scanf("%d",&n);
    for (int i = 1,u,v,val;i < n;i++) scanf("%d%d%d",&u,&v,&val),adj[u].pb({v,val}),adj[v].pb({u,val});
    for (int i = 1;i <= n;i++) if (adj[i].size() == 2) return printf("NO\n"),0;
    printf("YES\n");
    for (int i = 1;i <= n;i++) if (adj[i].size() == 1) {rt = i,dfs(adj[i][0].fi,i,adj[i][0].se); break;}
    printf("%d\n",ans.size());
    for (ppi p : ans) printf("%d %d %d\n",p.fi.fi,p.fi.se,p.se);
    return 0;
}


#include <bits/stdc++.h>

#define int long long
typedef long long ll;
using namespace std;

const int N = 2e5 + 10;
vector<int> g[N];
vector<int> e[N];
//vector<int> cur[N];
vector<tuple<int, int, int>> ans;
int rt;
int tmp[N];

pair<int, int> dfs(int u, int from) {
    if (u != rt && g[u].size() == 1) return {u, u};
    int l = -1, r = -1;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i], w = e[u][i];
        if (v == from)continue;
        int d = w - tmp[v];
        auto p = dfs(v, u);
        tmp[u] += w;
        ans.emplace_back(rt, p.first, d / 2);
        ans.emplace_back(rt, p.second, d / 2);
        ans.emplace_back(p.first, p.second, -d);
        if (l == -1)l = p.first;
        else if (r == -1) r = p.first;
    }
    return {l, r};
}

int32_t main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n - 1; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back(v), g[v].push_back(u);
        e[u].push_back(w), e[v].push_back(w);
    }
    for (int i = 1; i <= n; i++)if (g[i].size() == 2)return cout << "NO" << endl, 0;
    for (int i = 1; i <= n; i++) {
        if (g[i].size() == 1) {
            rt = i;
            dfs(i, -1);
            break;
        }
    }
    cout << "YES" << endl;
    int cnt = 0;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cnt++;
    }
    cout << cnt << endl;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cout << get<0>(p) << " " << get<1>(p) << " " << get<2>(p) << endl;
    }
}


#include <bits/stdc++.h>

#define int long long
typedef long long ll;
using namespace std;

const int N = 2e5 + 10;
vector<int> g[N];
vector<int> e[N];
//vector<int> cur[N];
vector<tuple<int, int, int>> ans;
int rt;
int tmp[N];

pair<int, int> dfs(int u, int from) {
    if (u != rt && g[u].size() == 1) return {u, u};
    int l = -1, r = -1;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i], w = e[u][i];
        if (v == from)continue;
        auto p = dfs(v, u);
        int d = w - tmp[v];
        tmp[u] += w;
        ans.emplace_back(rt, p.first, d / 2);
        ans.emplace_back(rt, p.second, d / 2);
        ans.emplace_back(p.first, p.second, -d);
        if (l == -1)l = p.first;
        else if (r == -1) r = p.first;
    }
    return {l, r};
}

int32_t main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n - 1; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back(v), g[v].push_back(u);
        e[u].push_back(w), e[v].push_back(w);
    }
    for (int i = 1; i <= n; i++)if (g[i].size() == 2)return cout << "NO" << endl, 0;
    for (int i = 1; i <= n; i++) {
        if (g[i].size() == 1) {
            rt = i;
            dfs(i, -1);
            break;
        }
    }
    cout << "YES" << endl;
    int cnt = 0;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cnt++;
    }
    cout << cnt << endl;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cout << get<0>(p) << " " << get<1>(p) << " " << get<2>(p) << endl;
    }
}


#include <bits/stdc++.h>

#define int long long
typedef long long ll;
using namespace std;

const int N = 2e5 + 10;
vector<int> g[N];
vector<int> e[N];
//vector<int> cur[N];
vector<tuple<int, int, int>> ans;
int rt;
int tmp[N];

pair<int, int> dfs(int u, int from) {
    if (u != rt && g[u].size() == 1) return {u, u};
    int l = -1, r = -1;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i], w = e[u][i];
        if (v == from)continue;
        auto p = dfs(v, u);
        int d = w - tmp[v];
        tmp[u] += w;
        ans.emplace_back(rt, p.first, d / 2);
        ans.emplace_back(rt, p.second, d / 2);
        ans.emplace_back(p.first, p.second, -d / 2);
        if (l == -1)l = p.first;
        else if (r == -1) r = p.first;
    }
    return {l, r};
}

int32_t main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n - 1; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back(v), g[v].push_back(u);
        e[u].push_back(w), e[v].push_back(w);
    }
    for (int i = 1; i <= n; i++)if (g[i].size() == 2)return cout << "NO" << endl, 0;
    for (int i = 1; i <= n; i++) {
        if (g[i].size() == 1) {
            rt = i;
            dfs(i, -1);
            break;
        }
    }
    cout << "YES" << endl;
    int cnt = 0;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cnt++;
    }
    cout << cnt << endl;
    for (auto p:ans) {
        if (get<0>(p) == get<1>(p))continue;
        cout << get<0>(p) << " " << get<1>(p) << " " << get<2>(p) << endl;
    }
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
int root;
vector<pii> G[1234];
vector<int> leaf[1234];
struct ops{
	int a,b,c;
	ops(int aa,int bb,int cc){
		a=aa;b=bb;c=cc;

	}
};
void dfs1(int cur,int pre){
	for(pii tmp:G[cur]){
		int nxt=tmp.first,val=tmp.second;
		if(pre==nxt) continue;
		dfs1(nxt,cur);
		leaf[cur].push_back(leaf[nxt][0]);
	}
	if(leaf[cur].size()==0) leaf[cur].push_back(cur);
}
vector<ops> ans;
void addpath(int cur,int val){
	if(leaf[cur].size()==1) ans.push_back(ops(root,leaf[cur][0],val));
	else{
		ans.push_back(ops(root,leaf[cur][0],val/2));
		ans.push_back(ops(root,leaf[cur][1],val/2));
		ans.push_back(ops(leaf[cur][0],leaf[cur][1],-val/2));
	}
}
void addedge(int cur,int pre,int val){
	if(pre==root) addpath(cur,val);
	else{
		addpath(cur,val);
		addpath(pre,-val);
	}
}
void dfs2(int cur,int pre){
	for(pii tmp:G[cur]){
		int nxt=tmp.first,val=tmp.second;
		if(pre==nxt) continue;
		addedge(nxt,cur,val);
		dfs2(nxt,cur);
	}
}
int main(){
	ios::sync_with_stdio();
	cin.tie(0);
	int n;cin>>n;
	for(int i=0;i<n-1;i++){
		int u,v,w;cin>>u>>v>>w;
		G[u].push_back(mp(v,w));
		G[v].push_back(mp(u,w));
	}
	for(int i=1;i<=n;i++) if(G[i].size()==2){cout<<"NO\n";return 0;}
	root=1;
	while(G[root].size()!=1) root++;
	dfs1(root,0);
	dfs2(root,0);
	cout<<"YES\n"<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++)
		cout<<ans[i].a<<' '<<ans[i].b<<' '<<ans[i].c<<endl;
}