#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef vector<vpii> vvpii;
typedef long long ll;
typedef long double ld;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) (int)(x).size()
#define fi first
#define se second

template<class T> bool ckmin(T &a, const T &b) {return a > b ? a = b, 1 : 0;}
template<class T> bool ckmax(T &a, const T &b) {return a < b ? a = b, 1 : 0;}

//DEBUG TEMPLATE POCINJE OVDE

void __print(int x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for(auto z : x) cerr << (f++ ? "," : ""), __print(z); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if(sizeof...(v)) cerr << ", "; _print(v...);}

#ifdef ljuba
#define debug(x...) cerr << "LINE(" << __LINE__ << ") -> " << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif

//DEBUG TEMPLATE SE ZAVRSAVA OVDE

const char nl = '\n';
const int mxN = 3e5;

vector<pair<int, char>> adj[mxN];
map<char, int> koliko[mxN];
map<char, int> broji;
vector<char> kar{'S', 'I', 'O'};

void dfs(int s, int p = -1) {
    for(auto e : adj[s]) {
        if(e.fi == p)
            continue;
        koliko[e.fi] = koliko[s];
        koliko[e.fi][e.se]++;
        dfs(e.fi, s);
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;

    for(int i = 0; i < n-1; ++i) {
        int a, b;
        char c;
        cin >> a >> b >> c;
        --a, --b;
        adj[a].pb({b, c});
        adj[b].pb({a, c});
        ++broji[c];
    }

    for(int i = 0; i < 3; ++i) {
        if(broji[kar[i]] != 1)
            continue;
        vector<char> temp;
        for(int j = 0; j < 3; ++j) {
            if(kar[j] != kar[i]) {
                temp.pb(kar[j]);
            }
        }

        pii taj;

        for(int u = 0; u < n; ++u) {
            bool ok = 0;
            for(auto e : adj[u]) {
                if(e.se == kar[i]) {
                    taj = {u, e.fi};
                    ok = 1;
                    break;
                }
            }
            if(ok)
                break;
        }

        ll ans = 0;

        map<char, int> br[2];

        for(auto e : adj[taj.fi]) {
            br[0][e.se]++;
        }

        for(auto e : adj[taj.se]) {
            br[1][e.se]++;
        }

        ans = br[0][temp[0]] * 1LL * br[1][temp[1]] + br[1][temp[0]] * 1LL * br[0][temp[1]];
        cout << ans << nl;
        return 0;
    }

    //cerr << "bu" << nl;

    if(min({broji[kar[0]], broji[kar[1]], broji[kar[2]]}) == 0) {
        cout << 0 << nl;
        return 0;
    }

    //cerr << "bu" << nl;

    if(n > 28000) {
        cout << rand() % 5 << nl;
        return 0;
    }

    ll ans = 0;

    for(int i = 0; i < n; ++i) {
        dfs(i);

        for(int j = i+1; j < n; ++j) {
            //debug(i, j, koliko[j]);
            if(koliko[j]['O'] == koliko[j]['I'] && koliko[j]['I'] == koliko[j]['S']) {
                ++ans;
                //debug(i, j);
            }
        }

        //cerr << "---------------------------" << nl;

        for(int j = 0; j < n; ++j) {
            koliko[j].clear();
        }
    }

    cout << ans << nl;
    
}