#include <bits/stdc++.h>
using namespace std;
int n;
typedef pair<int,int> Sio;
vector <vector <pair <int,Sio> > > Graph;

Sio f(char x){
if(x=='S')return {-1,-1};
if(x=='I')return {1,0};
if(x=='O')return {0,1};
}
Sio Add(Sio a,Sio b){
return make_pair(a.first+b.first,a.second+b.second);
}
Sio neg(Sio x){
    return make_pair(-x.first,-x.second);
}

vector <vector <int> > decompo;

vector <int> SubtreeSize;
vector <bool> blocked;
vector <int> parent;
vector <bool> InitBio;
void Init(int node,int prev=-1){
if(InitBio[node])return;
InitBio[node]=true;
SubtreeSize[node]=1;
parent[node]=prev;
for(pair <int,Sio> x:Graph[node]){
    Init(x.first,node);
    if(prev!=x.first)
    SubtreeSize[node]+=SubtreeSize[x.first];
}

}
int root=-1;

int DFS(int node,bool roott=0){
queue<int> q;
q.push(node);
int centroid=node;
int bestSize=SubtreeSize[node];

while(q.size()){
    int curr=q.front();
    q.pop();
    if(blocked[curr])continue;
    int MaxSub=0;
        MaxSub=SubtreeSize[node]-SubtreeSize[curr];


    for(pair <int,Sio> x:Graph[curr]){

    if(!blocked[x.first]&&parent[curr]!=x.first){
        q.push(x.first);
       MaxSub=max(MaxSub,SubtreeSize[x.first]);

    }
    }
    if(MaxSub<bestSize){
        centroid=curr;
        bestSize=MaxSub;
    }

}
    if(roott)root=centroid;
  blocked[centroid]=true;

for(pair <int,Sio> x:Graph[centroid]){
    if(!blocked[x.first])decompo[centroid].push_back(DFS(x.first));
}
  return centroid;

}
vector <Sio> Val;
void SioDist(int node,Sio dist,vector <int>&all){
    if(blocked[node])return;
    all.push_back(node);
    Val[node]=Add(Val[parent[node]],dist);
    for(pair <int,Sio> x:Graph[node]){
        if(x.first!=parent[node]&&!blocked[x.first])SioDist(x.first,x.second,all);
    }


}
int Resi(){
    queue <int> q;
    q.push(root);
    int rez=0;
    while(q.size()){
        int curr=q.front();
        q.pop();
        Val[curr]={0,0};
    map<Sio,int> cnt;
        for(pair<int,Sio> x:Graph[curr]){
            if(!blocked[x.first]&&x.first!=parent[curr]){
                vector <int> all;
                SioDist(x.first,x.second,all);
                for(int y:all){
                    rez+=cnt[neg(Val[y])];
                    rez+=(Val[y]==make_pair(0,0));


                }
                for(int y:all){
                    cnt[Val[y]]++;

                }

            }
        }
        blocked[curr]=1;
        for(int x:decompo[curr])q.push(x);

    }
return rez;
}


int main(){

cin >>n;
Graph.resize(n);
parent.resize(n);
InitBio.resize(n);
decompo.resize(n);
blocked.resize(n);
SubtreeSize.resize(n);
Val.resize(n);

for(int i=0;i<n-1;i++){
    int x,y;
    cin >>x>>y;
    x--;
    y--;
    char s='S';
    cin >>s;
    Graph[x].push_back({y,f(s)});
    Graph[y].push_back({x,f(s)});

}
Init(0);
DFS(0,1);
for(int i=0;i<n;i++)blocked[i]=0;
cout <<Resi()<<endl;
/*
for(int i=0;i<decompo.size();i++){
        cout <<i<<" : ";
for(int j=0;j<decompo[i].size();j++){
    cout <<decompo[i][j]<<" ";
}
cout <<endl;
}*/
}