#include <bits/stdc++.h>
using namespace std;
const int BUF = 100005;
const long long INF = 1LL << 62;
class Edge {
 public:
  int dst, cost;
  bool isTrain;
  Edge() {}
  Edge(int dst, int cost, bool isTrain)
      : dst(dst), cost(cost), isTrain(isTrain) {}
};
class QData {
 public:
  int node, cost;
  QData() {}
  QData(int node, int cost) : node(node), cost(cost) {}
  bool operator<(const QData &opp) const { return cost > opp.cost; }
};
int N;
vector<Edge> adj[BUF];
void read() {
  for (int i = 0; i < BUF; ++i) adj[i].clear();
  int nEdge, nTrain;
  cin >> N >> nEdge >> nTrain;
  for (int i = 0; i < nEdge; ++i) {
    int s, t, c;
    cin >> s >> t >> c;
    --s, --t;
    adj[s].push_back(Edge(t, c, false));
    adj[t].push_back(Edge(s, c, false));
  }
  for (int i = 0; i < nTrain; ++i) {
    int t, c;
    cin >> t >> c;
    --t;
    adj[0].push_back(Edge(t, c, true));
  }
}
void work() {
  priority_queue<QData> Q;
  long long cost[BUF];
  bool preTrain[BUF];
  for (int i = 0; i < N; ++i) {
    cost[i] = INF;
    preTrain[i] = false;
  }
  cost[0] = 0;
  Q.push(QData(0, 0));
  while (!Q.empty()) {
    QData cur = Q.top();
    Q.pop();
    if (cost[cur.node] < cur.cost) continue;
    for (int i = 0; i < adj[cur.node].size(); ++i) {
      Edge &e = adj[cur.node][i];
      if (cost[e.dst] > cost[cur.node] + e.cost) {
        cost[e.dst] = cost[cur.node] + e.cost;
        preTrain[e.dst] = e.isTrain;
        Q.push(QData(e.dst, cost[e.dst]));
      } else if (cost[e.dst] == cost[cur.node] + e.cost && !e.isTrain) {
        preTrain[e.dst] = false;
      }
    }
  }
  bool used[BUF] = {};
  int ans = 0;
  for (int i = 0; i < adj[0].size(); ++i) {
    Edge &e = adj[0][i];
    if (!e.isTrain) continue;
    if (!preTrain[e.dst] || used[e.dst])
      ++ans;
    else {
      used[e.dst] = true;
    }
  }
  cout << ans << endl;
}
int main() {
  read();
  work();
  return 0;
}
