#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    City() : d((unsigned long long)1 << 63), prev(0), bPrevTrack(false), bInQ(false) {}
    unsigned long long d; // shortest distance from capital
    int prev;
    bool bPrevTrack;
    bool bInQ;
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

bool LessThan(int i, int j)
{
    City& ci = cities[i];
    City& cj = cities[j];

    if (ci.d != cj.d) return ci.d < cj.d;
    if (ci.bPrevTrack != cj.bPrevTrack) return ci.bPrevTrack;
    if (i != j) return i < j;
    return false;
}

deque<int> dq;

// SPFA Algorithm
inline void UpdateDistance(int ci, unsigned long long d, bool bTrack)
{
    if ((d < cities[ci].d) || (d == cities[ci].d && cities[ci].bPrevTrack && !bTrack))
    {
        cities[ci].d = d;
        cities[ci].bPrevTrack = bTrack;
        if (!cities[ci].bInQ)
        {
            cities[ci].bInQ = true;
            dq.push_back(ci);
        }
        if (dq.size() >= 2 && dq.back() < dq.front()) swap(dq.front(), dq.back());  // small label first optimization SLF
    }
}

int main(void)
{
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    City& capitol = cities[1];
    capitol.d = 0;

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);

        if (roads[i].u == 1 || roads[i].v == 1)
        {
            int oi = roads[i].u == 1 ? roads[i].v : roads[i].u;
            UpdateDistance(oi, (unsigned long long)roads[i].x, false);
        }
        else
        {
            cities[roads[i].u].roads.push_back(i);
            cities[roads[i].v].roads.push_back(i);
        }
    }

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        UpdateDistance(s, (unsigned long long)y, true);
    }

    while (!dq.empty())
    {
        int ci = dq.front(); dq.pop_front();
        City& city = cities[ci];
        city.bInQ = false;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            int oci = road.u == ci ? road.v : road.u;
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            UpdateDistance(oci, otherCityDistanceUsingRoad, false);
        }
    }

    int usedTrackCount = 0;
    for (int i = 2; i <= n; ++i) if (cities[i].bPrevTrack) usedTrackCount++;
    cout << k - usedTrackCount;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    City() : d((unsigned long long)1 << 63), prev(0), bPrevTrack(false), bInQ(false) {}
    unsigned long long d; // shortest distance from capital
    int prev;
    bool bPrevTrack;
    bool bInQ;
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

deque<int> dq;
unsigned long long total = 0;

// SPFA Algorithm
inline void UpdateDistance(int ci, unsigned long long d, bool bTrack)
{
    if ((d < cities[ci].d) || (d == cities[ci].d && cities[ci].bPrevTrack && !bTrack))
    {
        unsigned long long oldDist = cities[ci].d;
        cities[ci].d = d;
        cities[ci].bPrevTrack = bTrack;
        if (!cities[ci].bInQ)
        {
            total += d;
            cities[ci].bInQ = true;
            if (!dq.empty() && d < cities[dq.front()].d) dq.push_front(ci); // Small Label First Optimization
            else dq.push_back(ci);
        }
        else total -= oldDist + d;

        unsigned long long avg = total / dq.size(); // Large Label Last Optimization
        while (cities[dq.front()].d > avg)
        {
            int idx = dq.front(); dq.pop_front();
            dq.push_back(idx);
        }
    }
}

int main(void)
{
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    City& capitol = cities[1];
    capitol.d = 0;

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);

        if (roads[i].u == 1 || roads[i].v == 1)
        {
            int oi = roads[i].u == 1 ? roads[i].v : roads[i].u;
            UpdateDistance(oi, (unsigned long long)roads[i].x, false);
        }
        else
        {
            cities[roads[i].u].roads.push_back(i);
            cities[roads[i].v].roads.push_back(i);
        }
    }

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        UpdateDistance(s, (unsigned long long)y, true);
    }

    while (!dq.empty())
    {
        int ci = dq.front(); dq.pop_front();
        City& city = cities[ci];
        city.bInQ = false;
        total -= cities[ci].d;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            int oci = road.u == ci ? road.v : road.u;
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            UpdateDistance(oci, otherCityDistanceUsingRoad, false);
        }
    }

    int usedTrackCount = 0;
    for (int i = 2; i <= n; ++i) if (cities[i].bPrevTrack) usedTrackCount++;
    cout << k - usedTrackCount;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    unsigned long long d; // shortest distance from capital
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

struct Node
{
    Node(int uu, int vv, int xx, bool track) : u(uu), v(vv), x(xx), bTrack(track) {}
    int u, v, x;
    bool bTrack;
};

bool operator>(const Node& n1, const Node& n2)
{
    if (n1.x != n2.x) return n1.x > n2.x;
    if (n1.u != n2.u) return n1.u > n2.u;
    if (n1.v != n2.v) return n1.v > n2.v;
    return (int)n1.bTrack > (int)n2.bTrack;
}

bool visited[300005];

int main(void)
{
    memset(visited, 0, sizeof(visited));
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    for (int i = 1; i <= n; ++i)
    {
        cities[i].d = (unsigned long long)1 << 63;
    }

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);
        cities[roads[i].u].roads.push_back(i);
        cities[roads[i].v].roads.push_back(i);
    }

    cities[0].d = 0;

    priority_queue<Node, vector<Node>, greater<Node> > pq;
    pq.push(Node(0, 1, 0, false));

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        pq.push(Node(1, s, y, true));
    }

    int usedTrackCount = 0;

    while (!pq.empty())
    {
        Node curNode(pq.top()); pq.pop();
        if (cities[curNode.v].d <= cities[curNode.u].d + (unsigned long long)curNode.x)
            continue;

        if (curNode.bTrack) usedTrackCount++;

        City& city = cities[curNode.v];
        city.d = cities[curNode.u].d + (unsigned long long)curNode.x;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            int ri = *it;
            if (visited[ri]) continue;
            visited[ri] = true;
            const Edge& road = roads[ri];
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            int u = road.u == curNode.v ? road.u : road.v;
            int v = road.u == curNode.v ? road.v : road.u;
            if (otherCityDistanceUsingRoad < cities[v].d)
                pq.push(Node(u, v, road.x, false));
        }
    }

    cout << k - usedTrackCount;// << endl;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    City() : d((unsigned long long)1 << 63), prev(0), bPrevTrack(false), bInQ(false) {}
    unsigned long long d; // shortest distance from capital
    int prev;
    bool bPrevTrack;
    bool bInQ;
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

bool LessThan(int i, int j)
{
    City& ci = cities[i];
    City& cj = cities[j];

    if (ci.d != cj.d) return ci.d < cj.d;
    if (ci.bPrevTrack != cj.bPrevTrack) return ci.bPrevTrack;
    if (i != j) return i < j;
    return false;
}

deque<int> dq;

// SPFA Algorithm
inline void UpdateDistance(int ci, unsigned long long d, bool bTrack)
{
    if ((d < cities[ci].d) || (d == cities[ci].d && cities[ci].bPrevTrack && !bTrack))
    {
        cities[ci].d = d;
        cities[ci].bPrevTrack = bTrack;
        if (!cities[ci].bInQ)
        {
            cities[ci].bInQ = true;
            dq.push_back(ci);
        }
        if (dq.back() < dq.front()) swap(dq.front(), dq.back());  // small label first optimization SLF
    }
}

int main(void)
{
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    City& capitol = cities[1];
    capitol.d = 0;

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);

        if (roads[i].u == 1 || roads[i].v == 1)
        {
            int oi = roads[i].u == 1 ? roads[i].v : roads[i].u;
            UpdateDistance(oi, (unsigned long long)roads[i].x, false);
        }
        else
        {
            cities[roads[i].u].roads.push_back(i);
            cities[roads[i].v].roads.push_back(i);
        }
    }

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        UpdateDistance(s, (unsigned long long)y, true);
    }

    while (!dq.empty())
    {
        int ci = dq.front(); dq.pop_front();
        City& city = cities[ci];
        city.bInQ = false;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            int oci = road.u == ci ? road.v : road.u;
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            UpdateDistance(oci, otherCityDistanceUsingRoad, false);
        }
    }

    int usedTrackCount = 0;
    for (int i = 2; i <= n; ++i) if (cities[i].bPrevTrack) usedTrackCount++;
    cout << k - usedTrackCount;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    City() : d((unsigned long long)1 << 63), prev(0), bPrevTrack(false), bInQ(false) {}
    unsigned long long d; // shortest distance from capital
    int prev;
    bool bPrevTrack;
    bool bInQ;
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

deque<int> dq;
unsigned long long total = 0;

// SPFA Algorithm
inline void UpdateDistance(int ci, unsigned long long d, bool bTrack)
{
    if ((d < cities[ci].d) || (d == cities[ci].d && cities[ci].bPrevTrack && !bTrack))
    {
        unsigned long long oldDist = cities[ci].d;
        cities[ci].d = d;
        cities[ci].bPrevTrack = bTrack;
        if (!cities[ci].bInQ)
        {
            total += d;
            cities[ci].bInQ = true;
            if (!dq.empty() && d < cities[dq.front()].d) dq.push_front(ci); // Small Label First Optimization
            else dq.push_back(ci);
        }
        else total = total - oldDist + d;

        unsigned long long avg = total / dq.size(); // Large Label Last Optimization
        while (cities[dq.front()].d > avg)
        {
            int idx = dq.front(); dq.pop_front();
            dq.push_back(idx);
        }
    }
}

int main(void)
{
    freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    City& capitol = cities[1];
    capitol.d = 0;

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);

        if (roads[i].u == 1 || roads[i].v == 1)
        {
            int oi = roads[i].u == 1 ? roads[i].v : roads[i].u;
            UpdateDistance(oi, (unsigned long long)roads[i].x, false);
        }
        else
        {
            cities[roads[i].u].roads.push_back(i);
            cities[roads[i].v].roads.push_back(i);
        }
    }

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        UpdateDistance(s, (unsigned long long)y, true);
    }

    while (!dq.empty())
    {
        int ci = dq.front(); dq.pop_front();
        City& city = cities[ci];
        city.bInQ = false;
        total -= cities[ci].d;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            int oci = road.u == ci ? road.v : road.u;
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            UpdateDistance(oci, otherCityDistanceUsingRoad, false);
        }
    }

    int usedTrackCount = 0;
    for (int i = 2; i <= n; ++i) if (cities[i].bPrevTrack) usedTrackCount++;
    cout << k - usedTrackCount;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    City() : d((unsigned long long)1 << 63), prev(0), bPrevTrack(false), bInQ(false) {}
    unsigned long long d; // shortest distance from capital
    int prev;
    bool bPrevTrack;
    bool bInQ;
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

deque<int> dq;

// SPFA Algorithm
inline void UpdateDistance(int ci, unsigned long long d, bool bTrack)
{
    if ((d < cities[ci].d) || (d == cities[ci].d && cities[ci].bPrevTrack && !bTrack))
    {
        cities[ci].d = d;
        cities[ci].bPrevTrack = bTrack;
        if (!cities[ci].bInQ)
        {
            cities[ci].bInQ = true;
            //if (!dq.empty() && d < dq.front()) dq.push_front(ci);
            //else
            dq.push_back(ci);
        }
    }
}

int main(void)
{
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    City& capitol = cities[1];
    capitol.d = 0;

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);

        if (roads[i].u == 1 || roads[i].v == 1)
        {
            int oi = roads[i].u == 1 ? roads[i].v : roads[i].u;
            UpdateDistance(oi, (unsigned long long)roads[i].x, false);
        }
        else
        {
            cities[roads[i].u].roads.push_back(i);
            cities[roads[i].v].roads.push_back(i);
        }
    }

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        UpdateDistance(s, (unsigned long long)y, true);
    }

    while (!dq.empty())
    {
        int ci = dq.front(); dq.pop_front();
        City& city = cities[ci];
        city.bInQ = false;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            int oci = road.u == ci ? road.v : road.u;
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            UpdateDistance(oci, otherCityDistanceUsingRoad, false);
        }
    }

    int usedTrackCount = 0;
    for (int i = 2; i <= n; ++i) if (cities[i].bPrevTrack) usedTrackCount++;
    cout << k - usedTrackCount;
}


#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

struct City
{
    unsigned long long d; // shortest distance from capital
    vector<int> roads;
};

struct Edge
{
    int u, v, x;
};

City cities[200005];
Edge roads[300005];

struct Node
{
    Node(int uu, int vv, int xx, bool track) : u(uu), v(vv), x(xx), bTrack(track) {}
    int u, v, x;
    bool bTrack;
};

bool operator>(const Node& n1, const Node& n2)
{
    if (n1.x != n2.x) return n1.x > n2.x;
    if (n1.u != n2.u) return n1.u > n2.u;
    if (n1.v != n2.v) return n1.v > n2.v;
    return (int)n1.bTrack > (int)n2.bTrack;
}

bool visited[100005];

int main(void)
{
    memset(visited, 0, sizeof(visited));
    //freopen("data.txt", "r", stdin);
    int n, m, k;
    fscanf(stdin, "%d %d %d", &n, &m, &k);

    for (int i = 1; i <= n; ++i)
    {
        cities[i].d = (unsigned long long)1 << 63;
    }

    for (int i = 0; i < m; ++i)
    {
        fscanf(stdin, "%d %d %d", &roads[i].u, &roads[i].v, &roads[i].x);
        cities[roads[i].u].roads.push_back(i);
        cities[roads[i].v].roads.push_back(i);
    }

    cities[0].d = 0;

    priority_queue<Node, vector<Node>, greater<Node> > pq;
    pq.push(Node(0, 1, 0, false));

    for (int i = 0; i < k; ++i)
    {
        int s, y;
        fscanf(stdin, "%d %d", &s, &y);
        pq.push(Node(1, s, y, true));
    }

    int usedTrackCount = 0;
    int visitCount = 0;

    while (!pq.empty())
    {
        Node curNode(pq.top()); pq.pop();
        if (cities[curNode.v].d <= cities[curNode.u].d + (unsigned long long)curNode.x)
            continue;

        if (curNode.bTrack) usedTrackCount++;

        City& city = cities[curNode.v];
        city.d = cities[curNode.u].d + (unsigned long long)curNode.x;

        for (vector<int>::const_iterator it(city.roads.begin()), itEnd(city.roads.end()); it != itEnd; ++it)
        {
            const Edge& road = roads[*it];
            unsigned long long otherCityDistanceUsingRoad = city.d + (unsigned long long)road.x;
            int u = curNode.v;
            int v = road.u == curNode.v ? road.v : road.u;
            if (!visited[v] && otherCityDistanceUsingRoad < cities[v].d)
                pq.push(Node(u, v, road.x, false));
        }

        visited[curNode.v] = true;
        //if (++visitCount == n) break;
    }

    cout << k - usedTrackCount;// << endl;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = INF;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	dijkstra(V, C);
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
	}
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || dist[sol[i].first] <= sol[i].second)
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i];
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i]) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) < N && dist[H[x * 2]] < dist[H[x]]) {
			son = x * 2;
			if (son < N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (son != x) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) < N && dist[H[x * 2]] < dist[H[x]]) {
				son = x * 2;
				if (son < N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = INF;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	dijkstra(V, C);
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
	}
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || dist[sol[i].first] <= sol[i].second)
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX], prevv[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		if (train[i] <= 1000000000) {
			dist[i] = train[i];
			prevv[i] = -1;
		}
		else {
			dist[i] = INF;
			prevv[i] = -1;
		}
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N / 2; i >= 1; i--)
		sift(i, N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] >= dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				prevv[V[x][i]] = x;
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (prevv[i] < 0) {
			use_train[i] = true;
		} else {
			use_train[i] = false;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000001;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i]) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N / 2; i >= 1; i--)
		sift(wh[i], N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX];
bool use_train[NMAX];
long long dist[NMAX], train[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i];
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i]) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = INF;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N && dist[H[x * 2]] < dist[H[x]]) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (son != x) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N && dist[H[x * 2]] < dist[H[x]]) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = INF;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	dijkstra(V, C);
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
	}
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || dist[sol[i].first] <= sol[i].second)
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N - 1; i >= 0; i--)
		percolate(wh[i]);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX], prevv[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		if (train[i] <= 1000000000) {
			dist[i] = train[i];
			prevv[i] = -1;
		}
		else {
			dist[i] = INF;
			prevv[i] = -1;
		}
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N / 2; i >= 1; i--)
		sift(i, N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] >= dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				prevv[V[x][i]] = x;
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (prevv[i] >= 0) {
			use_train[i] = true;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000001;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = 0; i < N / 2; i++)
		sift(wh[i], N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

#define NMAX 1024

int N, M, K, P, A[NMAX][NMAX];
long long R[NMAX * NMAX], C[NMAX * NMAX];

void calc(vector<long long>& V, long long wh[], int nn) {
	wh[0] = 0;
	priority_queue<long long> Q(V.begin(), V.end());
	for (int x = 1; x <= K; x++) {
		wh[x] = wh[x - 1];
		long long elem = Q.top();
		Q.pop();
		wh[x] += elem;
		elem -= nn * P;
		Q.push(elem);
	}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);

	scanf("%d %d %d %d", &N, &M, &K, &P);
	for (int i = 0; i < N; i++)
		for (int j = 0; j < M; j++)
			scanf("%d", &A[i][j]);
	vector<long long> V;
	for (int i = 0; i < N; i++) {
		long long sum = 0;
		for (int j = 0; j < M; j++)
			sum += A[i][j];
		V.push_back(sum);
	}
	calc(V, R, M);
	V.clear();
	for (int j = 0; j < M; j++) {
		long long sum = 0;
		for (int i = 0; i < N; i++)
			sum += A[i][j];
		V.push_back(sum);
	}
	calc(V, C, N);
	long long ret = (-(long long)999999999) * 999999999;
	for (int i = 0; i <= K; i++) {
		long long pos_ret = R[i] + C[K - i];
		pos_ret -= ((long long)i) * (K - i) * P;
		if (pos_ret > ret)
			ret = pos_ret;
	}
	printf("%I64d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		if (train[i] <= 1000000000)
			dist[i] = train[i] + 1;
		else
			dist[i] = INF;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N / 2; i >= 1; i--)
		sift(i, N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000001;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = 0; i < N / 2; i++)
		sift(wh[i]);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define pb push_back
#define NMAX 100000
#define INF 1000000000000000000LL

int N, M, K;

int H[2 * NMAX + 2], wh[NMAX], train[NMAX];
bool use_train[NMAX];
long long dist[NMAX];

void sift(int x, int N) {
		int son = x;
		if ((x * 2) <= N) {
			son = x * 2;
			if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
				son++;
		}
		while (dist[H[son]] < dist[H[x]]) {
			int aux = H[son];
			H[son] = H[x];
			H[x] = aux;
			wh[H[son]] = son;
			wh[H[x]] = x;
			x = son;
			if ((x * 2) <= N) {
				son = x * 2;
				if (son <= N - 1 && dist[H[son + 1]] < dist[H[son]])
					son++;
			}
		}
}

void percolate(int x) {
	int aux = H[x];
	while (x > 1 && dist[aux] < dist[H[x >> 1]]) {
		H[x] = H[x >> 1];
		wh[H[x]] = x;
		x >>= 1;
	}
	H[x] = aux;
	wh[H[x]] = x;
}

void dijkstra(vector<vector<int> >& V, vector<vector<int> >& C) {
	for (int i = 0; i < N; i++)
		dist[i] = train[i] + 1;
	dist[0] = 0;
	for (int i = 0; i < N; i++) {
		H[i + 1] = i;
		wh[i] = i + 1;
	}
	for (int i = N / 2; i >= 1; i--)
		sift(i, N);
	int n = N;
	while (n) {
		int x = H[1];
		H[1] = H[n--];
		sift(1, n);
		for (int i = 0; i < V[x].size(); i++) {
			if (dist[V[x][i]] > dist[x] + C[x][i]) {
				dist[V[x][i]] = dist[x] + C[x][i];
				percolate(wh[V[x][i]]);
			}
		}
	}
	for (int i = 0; i < N; i++)
		if (dist[i] != train[i] + 1) {
			use_train[i] = false;
		} else {
			use_train[i] = true;
			dist[i]--;
		}
}

int main()
{
  //freopen("b.in", "r", stdin);
  //freopen("b.out", "w", stdout);
	scanf("%d %d %d", &N, &M, &K);
	vector<vector<int> > V(N), C(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--; b--;
		V[a].pb(b);
		V[b].pb(a);
		C[a].pb(c);
		C[b].pb(c);
	}
	int ret = 0;
	vector<pair<int, int> > sol;
	for (int i = 0; i < N; i++)
		train[i] = 1000000000;
	for (int i = 0; i < K; i++) {
		int a, c;
		scanf("%d %d", &a, &c);
		a--;
		sol.pb(make_pair(a, c));
		train[a] = min(train[a], c);
	}
	dijkstra(V, C);
	sort(sol.begin(), sol.end());
	for (int i = 0; i < K; i++) {
		bool new_i = true;
		if (i > 0 && sol[i].first == sol[i - 1].first)
			new_i = false;
		if (new_i == false || !use_train[sol[i].first])
			ret++;
	}
	printf("%d\n", ret);
  return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[M];
L del[M];
L in[M];
int n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    cin >> n >> m >> k;
    rp(i, m)
    {
        L x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        cin >> x >> z;
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, 1L << 60);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    cout << ans << endl;

}


#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define rp(i, n) for(ll i = 0; i < (n); i++)
#define ll unsigned long long int
#define P pair<ll, ll>
#define PP pair<P, ll>
#define X first
#define Y second
#define M 310005
vector<P> a[M], tmp[M];
vector<P> add;
vector<P> notadd;
vector<P> edg;
ll _counter;
ll n, m, k;
class sor{
public:
    bool operator()(P x, P y){
        return x.Y > y.Y;
    }
};
ll d[M];
bool mark[M];
priority_queue<P, vector<P>, sor> q;
int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> k;
    rp(i, m){
        ll x, y,z;
        cin >> x >> y >> z;
        x--;
        y--;
        tmp[x].push_back(P(y, z));
        tmp[y].push_back(P(x, z));
    }
    rp(i, k){
        ll x, z;
        cin >> x >> z;
        x--;
        notadd.push_back(P(x, z));
        mark[x] = 1;
    }
    rp(i, n)sort(tmp[i].begin(), tmp[i].end());
    rp(i, n){
        size_t s = tmp[i].size();
        rp(j, s)
        {
            if(j == 0 || tmp[i][j].X != tmp[i][j-1].X)
                a[i].push_back(tmp[i][j]);
        }
    }
    //    rp(i, n){
    //        cout << i+1 << " " << tmp[i].size() << ":\n";
    //        for(auto x: tmp[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    //    rp(i, n){
    //        cout << i+1 << " " << a[i].size() << ":\n";
    //        for(auto x: a[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    sort(notadd.begin(), notadd.end());
    rp(i, k)
    {
        if(i == 0 || notadd[i].X != notadd[i-1].X)
        {// you need one at least so if 10 equals you need the first one sowieso and non else
            add.push_back(notadd[i]);
        }
        else
        {
            _counter++;
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    k = add.size();
    rp(i, k){
        d[add[i].X] = add[i].Y;
        q.push(P(add[i].X, add[i].Y));
    }
    while(!q.empty())
    {
        P t = q.top();
        q.pop();
        ll nd = t.X, ds = t.Y;
        if(d[y]<ds)continue;
        ll s = a[nd].size();
        rp(i, s){
            ll nx = a[nd][i].X;
            ll dEdge = a[nd][i].Y;
            ll dnx = dEdge + ds;
            if(dnx <= d[nx])
            {
                if(mark[nx]){
                    mark[nx] = false;
                    _counter++;
                }
            }
            if(dnx < d[nx])
            {
                d[nx] = dnx;
                q.push(P(nx, dnx));
            }
        }
    }
    cout << _counter << endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define rp(i, n) for(ll i = 0; i < (n); i++)
#define ll unsigned long long int
#define P pair<ll, ll>
#define PP pair<P, ll>
#define X first
#define Y second
#define M 310005
vector<P> a[M], tmp[M];
vector<P> add;
vector<P> notadd;
vector<P> edg;
ll _counter;
ll n, m, k;
class sor{
public:
    bool operator()(P x, P y){
        return x.Y > y.Y;
    }
};
ll d[M];
bool mark[M];
priority_queue<P, vector<P>, sor> q;
int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> k;
    rp(i, m){
        ll x, y,z;
        cin >> x >> y >> z;
        x--;
        y--;
        tmp[x].push_back(P(y, z));
        tmp[y].push_back(P(x, z));
    }
    rp(i, k){
        ll x, z;
        cin >> x >> z;
        x--;
        notadd.push_back(P(x, z));
        mark[x] = 1;
    }
    rp(i, n)sort(tmp[i].begin(), tmp[i].end());
    rp(i, n){
        size_t s = tmp[i].size();
        rp(j, s)
        {
            if(j == 0 || tmp[i][j].X != tmp[i][j-1].X)
                a[i].push_back(tmp[i][j]);
        }
    }
    //    rp(i, n){
    //        cout << i+1 << " " << tmp[i].size() << ":\n";
    //        for(auto x: tmp[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    //    rp(i, n){
    //        cout << i+1 << " " << a[i].size() << ":\n";
    //        for(auto x: a[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    sort(notadd.begin(), notadd.end());
    rp(i, k)
    {
        if(i == 0 || notadd[i].X != notadd[i-1].X)
        {// you need one at least so if 10 equals you need the first one sowieso and non else
            add.push_back(notadd[i]);
        }
        else
        {
            _counter++;
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    k = add.size();
    rp(i, k){
        d[add[i].X] = add[i].Y;
        q.push(P(add[i].X, add[i].Y));
    }
    while(!q.empty())
    {
        P t = q.top();
        q.pop();
        ll nd = t.X, ds = t.Y;
        ll s = a[nd].size();
        rp(i, s){
            ll nx = a[nd][i].X;
            ll dEdge = a[nd][i].Y;
            ll dnx = dEdge + ds;
            if(dnx <= d[nx])
            {
                if(mark[nx]){
                    mark[nx] = false;
                    _counter++;
                }
            }
            if(dnx < d[nx])
            {
                d[nx] = dnx;
                q.push(P(nx, dnx));
            }
        }
    }
    cout << _counter << endl;
    return 0;
}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 110005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[M];
L del[M];
L in[M];
L n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    scanf("%I64u", &n);
    scanf("%I64u", &m);
    scanf("%I64u", &k);
    rp(i, m)
    {
        L x, y, z;

        scanf("%I64u", &x);
        scanf("%I64u", &y);
        scanf("%I64u", &z);
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        scanf("%I64u", &x);
        scanf("%I64u", &z);
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%I64u\n", ans);
    return 0;

}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define pp pair<int, int>
#define pl pair<pp, bool>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%d", &n)
vector<pl> a[M], b[M];
L d[M];
int del[M];
int in[M];
int n, m, k;
int ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        int x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        b[x].push_back(pl(pp(y, z), 0));
        b[y].push_back(pl(pp(x, z), 0));
    }
    rp(i, k)
    {
        int x, z;
        read(x);
        read(z);
        x--;
        b[0].push_back(pl(pp(x, z), 1));
    }
    rp(i, n){
        sort(b[i].begin(), b[i].end());
        L s = b[i].size();
        rp(j, s)
        {
            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
            {
                a[i].push_back(b[i][j]);
            }
            else
            {
                ans += b[i][j].Y;
            }
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        if(d[id] > dst)continue;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%d\n", ans);
    return 0;

}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define pp pair<int, int>
#define pl pair<pp, bool>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%d", &n)
vector<pl> a[M], b[M];
L d[M];
int del[M];
int in[M];
int n, m, k;
int ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        int x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        a[x].push_back(pl(pp(y, z), 0));
        a[y].push_back(pl(pp(x, z), 0));
    }
    rp(i, k)
    {
        int x, z;
        read(x);
        read(z);
        x--;
        a[0].push_back(pl(pp(x, z), 1));
    }
//    rp(i, n){
//        sort(b[i].begin(), b[i].end());
//        L s = b[i].size();
//        rp(j, s)
//        {
//            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
//            {
//                a[i].push_back(b[i][j]);
//            }
//            else
//            {
//                ans += b[i][j].Y;
//            }
//        }
//    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        if(d[id] > dst)continue;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%d\n", ans);
    return 0;

}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%I64u", &n)
vector<PL> a[M], b[M];
L d[M];
L del[M];
L in[M];
L n, m, k;
L ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        L x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        b[x].push_back(PL(P(y, z), 0));
        b[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        read(x);
        read(z);
        x--;
        b[0].push_back(PL(P(x, z), 1));
    }
    rp(i, n){
        sort(b[i].begin(), b[i].end());
        L s = b[i].size();
        rp(j, s)
        {
            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
            {
                a[i].push_back(b[i][j]);
            }
            else
            {
                ans += b[i][j].Y;
            }
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        if(d[i] > dst)continue;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%llu\n", ans);
    return 0;

}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[M];
L del[M];
L in[M];
int n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    ios::sync_with_stdio(0);
    cin >> n >> m >> k;
    rp(i, m)
    {
        L x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        cin >> x >> z;
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    cout << ans << endl;

}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<int, L>
#define pp pair<int, int>
#define pl pair<pp, bool>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%d", &n)
vector<pl> a[M], b[M];
L d[M];
int del[M];
int in[M];
int n, m, k;
int ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        int x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        a[x].push_back(pl(pp(y, z), 0));
        a[y].push_back(pl(pp(x, z), 0));
    }
    rp(i, k)
    {
        int x, z;
        read(x);
        read(z);
        x--;
        a[0].push_back(pl(pp(x, z), 1));
    }
//    rp(i, n){
//        sort(b[i].begin(), b[i].end());
//        L s = b[i].size();
//        rp(j, s)
//        {
//            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
//            {
//                a[i].push_back(b[i][j]);
//            }
//            else
//            {
//                ans += b[i][j].Y;
//            }
//        }
//    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        int id = tmp.X;
        L dst = tmp.Y;
        if(d[id] < dst)continue;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%d\n", ans);
    return 0;

}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[M];
L del[M];
L in[M];
int n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    cin >> n >> m >> k;
    rp(i, m)
    {
        L x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        cin >> x >> z;
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, 1L << 30);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    cout << ans << endl;

}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%I64u", &n)
vector<PL> a[M], b[M];
L d[M];
L del[M];
L in[M];
L n, m, k;
L ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        L x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        b[x].push_back(PL(P(y, z), 0));
        b[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        read(x);
        read(z);
        x--;
        b[0].push_back(PL(P(x, z), 1));
    }
    rp(i, n){
        sort(b[i].begin(), b[i].end());
        L s = b[i].size();
        rp(j, s)
        {
            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
            {
                a[i].push_back(b[i][j]);
            }
            else
            {
                ans += b[i][j].Y;
            }
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%llu\n", ans);
    return 0;

}


#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[210005];
L del[210005];
L in[210005];
int n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    cin >> n >> m >> k;
    rp(i, m)
    {
        L x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        cin >> x >> z;
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, 1L << 63);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        L s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        L s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    cout << ans << endl;

}


#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define rp(i, n) for(ll i = 0; i < (n); i++)
#define ll unsigned long long int
#define P pair<ll, ll>
#define PP pair<P, ll>
#define X first
#define Y second
#define MX (1L<<63)
#define M 310005
vector<P> a[M], tmp[M];
vector<P> add;
vector<P> notadd;
vector<P> edg;
ll _counter;
ll n, m, k;
class sor{
public:
    bool operator()(P x, P y){
        return x.Y > y.Y;
    }
};
ll d[M];
bool mark[M];
priority_queue<P, vector<P>, sor> q;
int main(){
    cin >> n >> m >> k;
    rp(i, m){
        ll x, y,z;
        cin >> x >> y >> z;
        x--;
        y--;
        tmp[x].push_back(P(y, z));
        tmp[y].push_back(P(x, z));
    }
    rp(i, k){
        ll x, z;
        cin >> x >> z;
        x--;
        notadd.push_back(P(x, z));
        mark[x] = 1;
    }
    rp(i, n)sort(tmp[i].begin(), tmp[i].end());
    rp(i, n){
        size_t s = tmp[i].size();
        rp(j, s)
        {
            if(j == 0 || tmp[i][j].X != tmp[i][j-1].X)
                a[i].push_back(tmp[i][j]);
        }
    }
    //    rp(i, n){
    //        cout << i+1 << " " << tmp[i].size() << ":\n";
    //        for(auto x: tmp[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    //    rp(i, n){
    //        cout << i+1 << " " << a[i].size() << ":\n";
    //        for(auto x: a[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    sort(notadd.begin(), notadd.end());
    rp(i, k)
    {
        if(i == 0 || notadd[i].X != notadd[i-1].X)
        {// you need one at least so if 10 equals you need the first one sowieso and non else
            add.push_back(notadd[i]);
        }
        else
        {
            _counter++;
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    k = add.size();
    rp(i, k){
        d[add[i].X] = add[i].Y;
        q.push(P(add[i].X, add[i].Y));
    }
    while(!q.empty())
    {
        P t = q.top();
        q.pop();
        ll nd = t.X, ds = t.Y;
        ll s = a[nd].size();
        rp(i, s){
            ll nx = a[nd][i].X;
            ll dEdge = a[nd][i].Y;
            ll dnx = dEdge + ds;
            if(dnx <= d[nx])
            {
                if(mark[nx]){
                    mark[nx] = false;
                    _counter++;
                }
            }
            if(dnx < d[nx])
            {
                d[nx] = dnx;
                q.push(P(nx, dnx));
            }
        }
    }
    cout << _counter << endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define rp(i, n) for(ll i = 0; i < (n); i++)
#define ll unsigned long long int
#define P pair<ll, ll>
#define PP pair<P, ll>
#define X first
#define Y second
#define M 310005
vector<P> a[M], tmp[M];
vector<P> add;
vector<P> notadd;
vector<P> edg;
ll _counter;
ll n, m, k;
class sor{
public:
    bool operator()(P x, P y){
        return x.Y > y.Y;
    }
};
ll d[M];
bool mark[M];
priority_queue<P, vector<P>, sor> q;
int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> k;
    rp(i, m){
        ll x, y,z;
        cin >> x >> y >> z;
        x--;
        y--;
        tmp[x].push_back(P(y, z));
        tmp[y].push_back(P(x, z));
    }
    rp(i, k){
        ll x, z;
        cin >> x >> z;
        x--;
        notadd.push_back(P(x, z));
        mark[x] = 1;
    }
    rp(i, n)sort(tmp[i].begin(), tmp[i].end());
    rp(i, n){
        size_t s = tmp[i].size();
        rp(j, s)
        {
            if(j == 0 || tmp[i][j].X != tmp[i][j-1].X)
                a[i].push_back(tmp[i][j]);
        }
    }
    //    rp(i, n){
    //        cout << i+1 << " " << tmp[i].size() << ":\n";
    //        for(auto x: tmp[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    //    rp(i, n){
    //        cout << i+1 << " " << a[i].size() << ":\n";
    //        for(auto x: a[i])cout << x.X + 1 << " " << x.Y << " | ";
    //        cout << endl;
    //    }
    sort(notadd.begin(), notadd.end());
    rp(i, k)
    {
        if(i == 0 || notadd[i].X != notadd[i-1].X)
        {// you need one at least so if 10 equals you need the first one sowieso and non else
            add.push_back(notadd[i]);
        }
        else
        {
            _counter++;
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    k = add.size();
    rp(i, k){
        d[add[i].X] = add[i].Y;
        q.push(P(add[i].X, add[i].Y));
    }
    while(!q.empty())
    {
        P t = q.top();
        q.pop();
        ll nd = t.X, ds = t.Y;
        if(d[nd]<ds)continue;
        ll s = a[nd].size();
        rp(i, s){
            ll nx = a[nd][i].X;
            ll dEdge = a[nd][i].Y;
            ll dnx = dEdge + ds;
            if(dnx <= d[nx])
            {
                if(mark[nx]){
                    mark[nx] = false;
                    _counter++;
                }
            }
            if(dnx < d[nx])
            {
                d[nx] = dnx;
                q.push(P(nx, dnx));
            }
        }
    }
    cout << _counter << endl;
    return 0;
}


#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
#define read(n) scanf("%I64u", &n)
vector<PL> a[M], b[M];
L d[M];
L del[M];
L in[M];
L n, m, k;
L ans;
class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    read(n);
    read(m);
    read(k);
    rp(i, m)
    {
        L x, y, z;

        read(x);
        read(y);
        read(z);
        x--; y--;
        b[x].push_back(PL(P(y, z), 0));
        b[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        read(x);
        read(z);
        x--;
        b[0].push_back(PL(P(x, z), 1));
    }
    rp(i, n){
        sort(b[i].begin(), b[i].end());
        L s = b[i].size();
        rp(j, s)
        {
            if(j == 0 || b[i][j].X.X != b[i][j-1].X.X)
            {
                a[i].push_back(b[i][j]);
            }
            else
            {
                ans += b[i][j].Y;
            }
        }
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        if(d[id] > dst)continue;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    printf("%llu\n", ans);
    return 0;

}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define L unsigned long long int
#define P pair<L, L>
#define PL pair<P, L>
#define X first
#define Y second
#define M 210005
#define rp(i, n) for ( L i = 0; i < (n) ; i++)
vector<PL> a[M];
L d[M];
L del[M];
L in[M];
int n, m, k;

class sor
{
public:
    bool operator()(const P& x, const P& y)
    {
        return x.Y > y.Y;
    }
};
priority_queue<P, vector<P>, sor> q;
int main(){
    cin >> n >> m >> k;
    rp(i, m)
    {
        L x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        a[x].push_back(PL(P(y, z), 0));
        a[y].push_back(PL(P(x, z), 0));
    }
    rp(i, k)
    {
        L x, z;
        cin >> x >> z;
        x--;
        a[0].push_back(PL(P(x, z), 1));
    }
    fill(d, d+n, -1);
    d[0] = 0;
    q.push(P(0,0));
    while(!q.empty())
    {
        P tmp = q.top();
        q.pop();
        L id = tmp.X;
        L dst = tmp.Y;
        size_t s = a[id].size();
        rp(i, s)
        {
            L nxt = a[id][i].X.X;
            L ed = a[id][i].X.Y;
            L dnxt = dst + ed;
            if(dnxt < d[nxt])
            {
                d[nxt] = dnxt;
                q.push(P(nxt, dnxt));
            }
        }
    }
    L ans = 0;
    rp(i, n){
        size_t s = a[i].size();
        rp(j, s){
            L nx = a[i][j].X.X;
            L ed = a[i][j].X.Y;
            if(d[nx] == d[i] + ed)
            {
                in[nx]++;
                del[nx] += a[i][j].Y;
            }
            else ans += a[i][j].Y;
        }
    }
    rp(i, n){
        if(in[i])
        ans+=min(in[i] - 1, del[i]);
    }
    cout << ans << endl;

}


/*
 * Author:  xtestw
 * Created Time:  2014/7/19 21:16:21
 * File Name: B.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
struct node
{
    int to;
    int w;
};
vector<node> mp[500010];
long long d[500010];
int vis[500010];

int n,m,k;
void spfa(int s)
{
    queue <int> q;
    memset(d,-1,sizeof(d));
    memset(vis,false,sizeof(vis));
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            if(d[v] <0 || d[v]>d[u]+(long long)mp[u][i].w)
            {
                d[v]=d[u]+(long long)mp[u][i].w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
   freopen("f:/in.txt","r",stdin);
#endif
    cin>>n>>m>>k;
    memset(d,-1,sizeof(d));
    for(int i=0;i<m;i++)
    {
        int u,x,v;
        scanf("%d%d%d",&u,&v,&x);
        node t;
        t.to=u;
        t.w=x;
        mp[v].push_back(t);
        node t2;
        t2.to=v;
        t2.w=x;
        mp[u].push_back(t2);
    }
    spfa(1);
    int ans=0;
    while (k--)
    {
        int s,y;
        scanf("%d%d",&s,&y);
        if (d[s]>=0 && d[s]<=(long long)y) ans++;
        if (d[s]<0) d[s]=(long long)y;
    }
    cout<<ans<<endl;
   return 0;
}


/*
 * Author:  xtestw
 * Created Time:  2014/7/19 21:16:21
 * File Name: B.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
struct node
{
    int to;
    int w;
};
vector<node> mp[500010];
long long d[500010];
int vis[500010];
struct route{
    int s,y;
};
int vis2[100010];
route r[100100];
int n,m,k;
int pre[100010];
void spfa(int s)
{
    queue <int> q;
    memset(vis,false,sizeof(vis));
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            if(d[v] <0 || d[v]>=d[u]+(long long)mp[u][i].w)
            {
                pre[v]=u;
                d[v]=d[u]+(long long)mp[u][i].w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}
int cmp(const route& a,const route& b)
{
    if (a.s!=b.s) return a.s<b.s;
    return a.y<b.y;
}
int main() {
#ifndef ONLINE_JUDGE
   freopen("f:/in.txt","r",stdin);
#endif
    cin>>n>>m>>k;
    memset(d,-1,sizeof(d));
    for(int i=0;i<m;i++)
    {
        int u,x,v;
        scanf("%d%d%d",&u,&v,&x);
        node t;
        t.to=u;
        t.w=x;
        mp[v].push_back(t);
        node t2;
        t2.to=v;
        t2.w=x;
        mp[u].push_back(t2);
        if (u==1){d[v]=d[v]<0?x:min(d[v],(long long)x);}
        if (v==1){d[u]=d[u]<0?x:min(d[u],(long long)x);}
    }
    int ans=0;
    memset(vis2,0,sizeof(vis2));
   for (int i=0;i<k;i++)
    {
        int s,y;
        scanf("%d%d",&s,&y);
        r[i].s=s;
        r[i].y=y;
        if (d[s]==y) {ans++; vis2[s]=1;}
        if (d[s]>y || d[s]<0){
            d[s]=y;
            pre[s]=1;
        }
    }
   sort(r,r+k,cmp);
    spfa(1);
   for (int i=0;i<k;i++)
   {
       int s=r[i].s;
       int y=r[i].y;
       if (i!=0 && r[i-1].s==s){ans++;vis2[s]=1;continue;}
       if (d[s]>0 && d[s]<(long long)y){ans++;vis2[s]=1;}
       if (d[s]>0 && d[s]==y && pre[s]!=1 && vis2[s]==0) {ans++;vis2[s]=1;}
   }
    cout<<ans<<endl;
   return 0;
}


/*
 * Author:  xtestw
 * Created Time:  2014/7/19 21:16:21
 * File Name: B.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
struct node
{
    int to;
    int w;
};
vector<node> mp[500010];
long long d[500010];
int vis[500010];
struct route{
    int s,y;
};
int vis2[100010];
route r[100100];
route r2[100100];
int n,m,k;
int pre[100010];
void spfa(int s)
{
    queue <int> q;
    memset(vis,false,sizeof(vis));
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            if(d[v] <0 || d[v]>=d[u]+(long long)mp[u][i].w)
            {
                if (d[v]==d[u]+(long long)mp[u][i].w && u==1){continue;}
                pre[v]=u;
                d[v]=d[u]+(long long)mp[u][i].w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}
int cmp(const route& a,const route& b)
{
    if (a.s!=b.s) return a.s<b.s;
    return a.y<b.y;
}
int main() {
#ifndef ONLINE_JUDGE
   freopen("f:/in.txt","r",stdin);
#endif
    cin>>n>>m>>k;
    memset(d,-1,sizeof(d));
    for(int i=0;i<m;i++)
    {
        int u,x,v;
        scanf("%d%d%d",&u,&v,&x);
        node t;
        t.to=u;
        t.w=x;
        mp[v].push_back(t);
        node t2;
        t2.to=v;
        t2.w=x;
        mp[u].push_back(t2);
        if (u==1){if (d[v]<0 || d[v]>x) d[v]=x;}
        if (v==1){if (d[u]<0 || d[u]>x) d[u]=x;}
    }
    int ans=0;
    memset(vis2,0,sizeof(vis2));
    memset(pre,-1,sizeof(pre));
    int tot=0;
    for (int i=0;i<k;i++)
    {
        int s,y;
        scanf("%d%d",&s,&y);
        r[i].s=s;
        r[i].y=y;
    }
    sort(r,r+k,cmp);
    for(int i=0;i<k;i++)
    {
        int s=r[i].s;
        int y=r[i].y;
        if (i>0 && r[i-1].s==s)
        {
            ans++;
        }else{
            r2[tot].s=s;
            r2[tot++].y=y;
            if (d[s]>0 && d[s]<=y){ans++; vis2[tot-1]=1;}
            if (d[s]<0 || d[s]>y){d[s]=y; pre[s]=1;}
        }
    }
   spfa(1);
   k=tot;
   for (int i=0;i<k;i++)
   {
       int s=r2[i].s;
       int y=r2[i].y;
       if (vis2[i]) continue;
       if (d[s]<(long long)y){ans++;}
       if (d[s]==(long long)y && pre[s]!=1){ans++;}
   }
    cout<<ans<<endl;
   return 0;
}


/*
 * Author:  xtestw
 * Created Time:  2014/7/19 21:16:21
 * File Name: B.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
struct node
{
    int to;
    int w;
};
vector<node> mp[500010];
long long d[500010];
int vis[500010];
struct route{
    int s,y;
};
route r[100100];
int n,m,k;
void spfa(int s)
{
    queue <int> q;
    memset(d,-1,sizeof(d));
    memset(vis,false,sizeof(vis));
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            if(d[v] <0 || d[v]>d[u]+(long long)mp[u][i].w)
            {
                d[v]=d[u]+(long long)mp[u][i].w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}
int cmp(const route& a,const route& b)
{
    if (a.s!=b.s) return a.s<b.s;
    return a.y<b.y;
}
int main() {
#ifndef ONLINE_JUDGE
   freopen("f:/in.txt","r",stdin);
#endif
    cin>>n>>m>>k;
    memset(d,-1,sizeof(d));
    for(int i=0;i<m;i++)
    {
        int u,x,v;
        scanf("%d%d%d",&u,&v,&x);
        node t;
        t.to=u;
        t.w=x;
        mp[v].push_back(t);
        node t2;
        t2.to=v;
        t2.w=x;
        mp[u].push_back(t2);
    }
    spfa(1);
    int ans=0;
   for (int i=0;i<k;i++)
    {
        int s,y;
        scanf("%d%d",&s,&y);
        r[i].s=s;
        r[i].y=y;
    }
   sort(r,r+k,cmp);
   for (int i=0;i<k;i++)
   {
       int s=r[i].s;
       int y=r[i].y;
       if (d[s]>0 && d[s]<=(long long)y){ans++;}
       if (d[s]<0 || d[s]>(long long)y){d[s]=(long long)y;}
   }
    cout<<ans<<endl;
   return 0;
}


/*
 * Author:  xtestw
 * Created Time:  2014/7/19 21:16:21
 * File Name: B.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
struct node
{
    int to;
    int w;
};
vector<node> mp[100010];
int d[100010];
int vis[100010];

    int n,m,k;
void spfa(int s)
{   queue <int> q;
    for(int i=1;i<=n;i++)
          d[i]=0x3f3f3f3f;
    memset(vis,false,sizeof(vis));
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            if(d[v]>d[u]+mp[u][i].w)
            {
                d[v]=d[u]+mp[u][i].w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
   freopen("f:/in.txt","r",stdin);
#endif
    cin>>n>>m>>k;
    memset(d,-1,sizeof(d));
    for(int i=0;i<m;i++)
    {
        int u,x,v;
        scanf("%d%d%d",&u,&v,&x);
        node t;
        t.to=u;
        t.w=x;
        mp[v].push_back(t);
        node t2;
        t2.to=v;
        t2.w=x;
        mp[u].push_back(t2);
    }
    spfa(1);
    int ans=0;
    while (k--)
    {
        int s,y;
        scanf("%d%d",&s,&y);
        if (d[s]<=y) ans++;
        if (d[s]==0x3f3f3f3f) d[s]=y;
    }
    cout<<ans<<endl;
   return 0;
}