#include using namespace std; using ll=long long; using ld=double; using vll=vector; using vvll=vector>; #define FOR(i,a,b) for(ll i=a;i<(ll)b;++i) #define F(n) FOR(i,0,n) #define FF(n) FOR(j,0,n) #define aa first #define bb second #define PB push_back #define EQ(a,b) (fabs(a-b)<=(fabs(a+b)*EPS)) #define MOD ((ll)(1e9+7)) #define dbg cerr #define out(n) cout << n << '\n' #define INF (1ll << 50) #define MXN 5 #define MXVERTEX (3*3*3*3*3*3) #define START (MXVERTEX-1) //#define dbg if(0)cerr ll n,m,q,c[3]; ll subtract(ll h1, ll h2) { ll res = 0; ll cur = 1; F(MXN+1) { res += cur*((h1+2*h2)%3); cur *= 3; h1 /= 3; h2 /= 3; } return res; } struct Dijkstra { struct Edge{ ll v,w; // destination and weight bool operator<(const Edge& a)const{return w>a.w;} }; ll n; vector> g; vll d,p; Dijkstra(ll n): n(n), g(vector>(n)), d(vll(n)), p(vll(n)) {} void add_edge(ll u,ll v,ll w){ g[u].PB({v,w}); if (u == 1) add_edge(START, v, w); if (v == 1) add_edge(u, START, w); } void run(ll s){ F(n)d[i]=INF,p[i]=-1; d[s]=0; priority_queue q; q.push({s,d[s]}); while(q.size()){ auto u=q.top().v;q.pop(); for(auto e:g[u]) if(d[e.v]>d[u]+e.w) { d[e.v]=d[u]+e.w,p[e.v]=u,q.push({e.v,d[e.v]}); assert(1e14); } } ll res=0; F(n) res += d[i]; F(n) if (d[i] == INF) d[i] = 0; } }; void print(vector> & g, ll n) { F(n){ FF(n){ dbg << g[i][j]; } dbg << '\n'; } dbg << endl; } ll countRes(Dijkstra & dj, const map & cnt) { ll res = 0; dj.run(START); for (auto i: cnt) { assert(dj.d[i.aa] <= INF); if (dj.d[i.aa] < INF) { res+=dj.d[i.aa]*i.bb; } } return res; } int main(){ ios::sync_with_stdio(0);cin.tie(0); c[0]=0; cin>>n>>m>>q>>c[1]>>c[2]; Dijkstra dj(MXVERTEX + 2); vector> g(MXVERTEX + 2); map hash; map cnt; ll cur=1; F(n){ cnt[cur] = 1; hash[i] = cur; cur *= 3; } cnt[1]=0; F(m){ ll u,v; char t; cin>>u>>v>>t; t = (t == 'O' ? 1 : 2); dj.add_edge(hash[u],hash[v],c[t]); dj.add_edge(hash[v],hash[u],c[t]); g[hash[u]][hash[v]] = t; g[hash[v]][hash[u]] = t; } set skipped; ll res = countRes(dj, cnt); F(q){ ll a,b; cin>>a>>b; if (skipped.count(a) || skipped.count(b)) { skipped.insert(n+i); out(res); continue; } ll oa = a; ll ob = b; a = hash[a]; b = hash[b]; if(g[a].count(b) && g[a][b] != 0){ skipped.insert(n+i); dbg << "invalid query " << oa << ' ' << ob << endl; out(res); continue; } ll sub = subtract(a, b); hash[i+n] = sub; cnt[sub] ++; if (cnt[sub] > 2) { // bucket full, just make it bigger if (dj.d[sub] < INF) res += dj.d[sub]; out(res); continue; } // create the new bucket vertex map ne; for (auto j: g[a]) { ne[j.aa] = (j.bb + 2*g[b][j.aa])%3; } for (auto j: g[b]) { ne[j.aa] = (2*j.bb + g[a][j.aa])%3; } for (auto j: ne) { if (j.bb==0)continue; dj.add_edge(sub,j.aa,c[j.bb]); dj.add_edge(j.aa,sub,c[j.bb]); g[j.aa][sub] = j.bb; g[sub][j.aa] = j.bb; } res=countRes(dj, cnt); out(res); } return 0; }