#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll LINF = (ll)9e18;
struct Edge {
int to;
int w;
};
struct DEdge {
int from, to;
ll w;
bool covered;
DEdge(int _f=0,int _t=0,ll _w=0):from(_f),to(_t),w(_w),covered(false){}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M, K;
if(!(cin >> N >> M >> K)) return 0;
vector<int> U(M), V(M);
vector<int> W(M);
vector<vector<Edge>> g(N+1);
for(int i=0;i<M;i++){
int u,v; int w;
cin >> u >> v >> w;
U[i]=u; V[i]=v; W[i]=w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
// data for K people: index 1 is Nam
vector<int> a(K+1), b(K+1), p(K+1, 1); // p unused for Nam
cin >> a[1] >> b[1];
for(int i=2;i<=K;i++){
int pi, ai, bi;
cin >> pi >> ai >> bi;
p[i] = pi; a[i] = ai; b[i] = bi;
}
auto dijkstra = [&](int src)->vector<ll>{
vector<ll> dist(N+1, LINF);
priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;
dist[src]=0;
pq.push({0, src});
while(!pq.empty()){
auto cur = pq.top(); pq.pop();
ll d = cur.first;
int u = cur.second;
if(d != dist[u]) continue;
for(const Edge &e : g[u]){
int v = e.to; ll nd = d + e.w;
if(nd < dist[v]){
dist[v] = nd;
pq.push({nd, v});
}
}
}
return dist;
};
// Dijkstra cho Nam: từ a1 và từ b1
vector<ll> distA1 = dijkstra(a[1]);
vector<ll> distB1 = dijkstra(b[1]);
ll D = distA1[b[1]];
if(D>=LINF){
// không có đường từ a1 tới b1 (không hợp lý theo đề nhưng phòng hờ)
cout << 0 << "\n";
return 0;
}
// Xây DAG gồm các cạnh (u->v) nằm trên một đường ngắn nhất từ a1 đến b1
vector<DEdge> dedges;
dedges.reserve(2*M);
vector<vector<int>> dagAdj(N+1); // lưu indices của dedges
for(int i=0;i<M;i++){
int u = U[i], v = V[i]; ll w = W[i];
// hướng u -> v
if(distA1[u] < LINF && distA1[v] < LINF && distA1[u] + w == distA1[v]){
if(distA1[v] + distB1[v] == D){
dedges.emplace_back(u, v, w);
dagAdj[u].push_back((int)dedges.size()-1);
}
}
// hướng v -> u
if(distA1[v] < LINF && distA1[u] < LINF && distA1[v] + w == distA1[u]){
if(distA1[u] + distB1[u] == D){
dedges.emplace_back(v, u, w);
dagAdj[v].push_back((int)dedges.size()-1);
}
}
}
// Với mỗi bạn (ngoại trừ Nam), chạy Dijkstra từ a_i và b_i, đánh dấu các directed-edge nào
// nằm trên một đường ngắn nhất của bạn đó; nếu bạn dễ tính p=1 -> luôn có thể thay đổi thời gian;
// nếu khó tính p=0 -> cần distAi[u] == distA1[u] để gặp tại bắt đầu cạnh.
for(int i=2;i<=K;i++){
vector<ll> distAi = dijkstra(a[i]);
vector<ll> distBi = dijkstra(b[i]);
ll Di = distAi[b[i]];
if(Di >= LINF) continue; // bạn này không có đường hợp lệ
// duyệt các directed edges
for(size_t idx=0; idx<dedges.size(); ++idx){
if(dedges[idx].covered) continue; // đã có ai cover thì khỏi kiểm tra
int u = dedges[idx].from, v = dedges[idx].to;
ll w = dedges[idx].w;
// cần kiểm tra cạnh có thuộc đường ngắn nhất của bạn i
if(distAi[u] < LINF && distAi[v] < LINF && distAi[u] + w == distAi[v] && distAi[v] + distBi[v] == Di){
if(p[i] == 1){
dedges[idx].covered = true;
}else{
// khó tính: bắt đầu điểm u phải đến đúng lúc như Nam
if(distAi[u] == distA1[u]){
dedges[idx].covered = true;
}
}
}
}
}
// DP tìm đường (a1 -> b1) trên DAG maximize tổng w của các cạnh được covered
// Sắp xếp các đỉnh theo distA1 tăng dần (đây là topological order trên DAG)
vector<int> order(N);
for(int i=0;i<N;i++) order[i] = i+1;
sort(order.begin(), order.end(), [&](int x, int y){
if(distA1[x] != distA1[y]) return distA1[x] < distA1[y];
return x < y;
});
vector<ll> dp(N+1, -LINF);
dp[a[1]] = 0;
for(int u : order){
if(dp[u] == -LINF) continue;
// duyệt các cạnh u -> v
for(int idx : dagAdj[u]){
int v = dedges[idx].to;
ll add = dedges[idx].covered ? dedges[idx].w : 0LL;
if(dp[u] + add > dp[v]){
dp[v] = dp[u] + add;
}
}
}
ll ans = dp[b[1]];
if(ans < 0) ans = 0; // phòng hờ
cout << ans << "\n";
return 0;
}