#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#define debug cout<<"debug"<<endl;
#define ll long long
using namespace std;

const int MAXNODE = 1e5 + 5;
const int INF = 0x3f3f3f3f;

struct Road
{
        int v, len;
};
struct Train
{
        int v, len;
};
int n, m, k;
vector <Road> G[MAXNODE];
vector <Train> route;
priority_queue<pair<ll, int> > que;
ll dis[MAXNODE];
ll cot[MAXNODE];
bool vis[MAXNODE];
void input()
{
        int u, v, len;
        for(int i = 0;i < m; i++)
        {
                cin>>u>>v>>len;
                G[u].push_back((Road){v, len});
                G[v].push_back((Road){u, len});
        }
        u = 1;
        for(int i = 0;i < k; i++)
        {
                cin>>v>>len;
                route.push_back((Train){v, len});
                G[u].push_back((Road){v, len});
                G[v].push_back((Road){u, len});
        }
}
void init()
{
        //debug;
        for(int i = 1;i <= n; i++)
            G[i].clear();
        route.clear();
        memset(cot, 0, sizeof(cot));
        memset(dis, INF, sizeof(dis));//or set to -1;
        memset(vis, false, sizeof(vis));
}
void Dijkstra(int tt)
{
    que.push(make_pair(0 * -1, tt));
    dis[tt] = 0;
    cot[tt] = 1;
    while(!que.empty())
    {
        //que.top().first;
        //que.top().second;
        ll val = -que.top().first;
        int u = que.top().second;
        que.pop();
        if(vis[u])  continue;
        vis[u] = true;
        for(int i = 0;i < G[u].size(); i++)
        {
            Road& e = G[u][i];
            if(dis[e.v] == val + e.len)
            {
                cot[e.v] += cot[u];
                if(cot[e.v] > 1e8)
                {
                    cot[e.v] = 1e8;
                }
                //que.push(make_pair(dis[e.v] * -1, e.v));
            }
            else if(dis[e.v] > val + e.len)
            {
                cot[e.v] = cot[u];
                dis[e.v] = val + e.len;
                que.push(make_pair(dis[e.v] * -1, e.v));
            }
        }

    }
    //for(int i = 1;i <= n; i++)  printf("%I64d ",dis[i]);  puts("");
}

ll Charge()
{
        //Train& e = route;
        /*for(int i = 1;i <= n; i++)
        {
            printf("%d ",dis[i]);
        }
        puts("");*/
        ll res = 0;
        for(int i = 0;i < route.size(); i++)
        {
            int v = route[i].v;
            int len = route[i].len;
            if(len > dis[v])    res++;
            else if((len == dis[v] && cot[v] > 1))
            {
                cot[v] --;
                res++;
            }
        }
        return res;
}
int main()
{
        while(scanf("%d%d%d", &n, &m, &k) != EOF)
        {
                init();
                input();
                Dijkstra(1);
                ll res = Charge();
                cout<<res<<endl;
        }
        return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {
    }
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  q.push(make_pair(0, 1));
  while(q.size()) {
    pii p = q.top();
    q.pop();
    ll u = p.second;
    if(vis[u])  continue;
    vis[u] = 1;
    for(int i=0; i<e[u].size(); i++) {
        Edge x = e[u][i];
        if(dis[x.v] > dis[u] + x.len) {
            cnt[x.v] = cnt[u];
            dis[x.v] = dis[u] + x.len;
            q.push(make_pair(dis[x.v], x.v));
        }
        else if(dis[x.v] == dis[u] + x.len)
            cnt[x.v] += cnt[u];
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
    dis[i] = inf;
    vis[i] =  0;
    cnt[i] = 0;
  }
  for(int i=1; i<=m; i++) {
    ll u, v, len;
    cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
    ll u = 1, v, len;
    cin >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  /*  cout << inf << endl;
  for(int i=1; i<=n; i++)
    printf("%lld ", dis[i]);
  puts("");
  */
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
     ll x = a[i].v;
     ll y = a[i].len;
     if(y > dis[x])  ans++;
     else if(y == dis[x] && cnt[x] > 1) {
        ans++;
        cnt[x]--;
     }
  }
  printf("%d\n", ans);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#define debug cout<<"debug"<<endl;
#define ll long long
using namespace std;

const int MAXNODE = 1e5 + 5;
const int INF = 0x3f3f3f3f;

struct Road
{
        int v, len;
};
struct Train
{
        int v, len;
};
int n, m, k;
vector <Road> G[MAXNODE];
vector <Train> route;
priority_queue<pair<ll, int> > que;
ll dis[MAXNODE];
ll cot[MAXNODE];
bool vis[MAXNODE];
void input()
{
        int u, v, len;
        for(int i = 0;i < m; i++)
        {
                cin>>u>>v>>len;
                G[u].push_back((Road){v, len});
                G[v].push_back((Road){u, len});
        }
        u = 1;
        for(int i = 0;i < k; i++)
        {
                cin>>v>>len;
                route.push_back((Train){v, len});
                G[u].push_back((Road){v, len});
                G[v].push_back((Road){u, len});
        }
}
void init()
{
        //debug;
        for(int i = 1;i <= n; i++)
            G[i].clear();
        route.clear();
        memset(cot, 0, sizeof(cot));
        memset(dis, INF, sizeof(dis));//or set to -1;
        memset(vis, false, sizeof(vis));
}
void Dijkstra(int tt)
{
    que.push(make_pair(0 * -1, tt));
    dis[tt] = 0;
    cot[tt] = 1;
    while(!que.empty())
    {
        //que.top().first;
        //que.top().second;
        ll val = -que.top().first;
        int u = que.top().second;
        que.pop();
        if(vis[u])  continue;
        vis[u] = true;
        for(int i = 0;i < G[u].size(); i++)
        {
            Road& e = G[u][i];
            if(dis[e.v] == val + e.len)
            {
                cot[e.v] += cot[u];
               /* if(cot[e.v] > 1e8)
                {
                    cot[e.v] = 1e8;
                }
                */
                //que.push(make_pair(dis[e.v] * -1, e.v));
            }
            else if(dis[e.v] > val + e.len)
            {
                cot[e.v] = cot[u];
                dis[e.v] = val + e.len;
                que.push(make_pair(dis[e.v] * -1, e.v));
            }
        }

    }
    //for(int i = 1;i <= n; i++)  printf("%I64d ",dis[i]);  puts("");
}

ll Charge()
{
        //Train& e = route;
        /*for(int i = 1;i <= n; i++)
        {
            printf("%d ",dis[i]);
        }
        puts("");*/
        ll res = 0;
        for(int i = 0;i < route.size(); i++)
        {
            int v = route[i].v;
            int len = route[i].len;
            if(len > dis[v])    res++;
            else if((len == dis[v] && cot[v] > 1))
            {
                cot[v] --;
                res++;
            }
        }
        return res;
}
int main()
{
        while(scanf("%d%d%d", &n, &m, &k) != EOF)
        {
                init();
                input();
                Dijkstra(1);
                ll res = Charge();
                cout<<res<<endl;
        }
        return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {
    }
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  q.push(make_pair(0, 1));
  while(!q.empty()) {
  	pii p = q.top();
  	q.pop();
  	ll u = p.second;
  	if(vis[u])  continue;
  	vis[u] = 1;
  	for(int i=0; i<e[u].size(); i++) {
  		Edge x = e[u][i];
  		if(dis[x.v] > dis[u] + x.len) {
  			cnt[x.v] = cnt[u];
  			//if(cnt[x.v] > 1e8) cnt[x.v] = 1e8;
  			dis[x.v] = dis[u] + x.len;
  			q.push(make_pair(dis[x.v], x.v));
  		}
  		else if(dis[x.v] == dis[u] + x.len) {
  			cnt[x.v] += cnt[u];
  			if(cnt[x.v > 1e8]) cnt[x.v] = 1e8;
  		}
  	}
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
  	dis[i] = inf;
  	vis[i] =  0;
  	cnt[i] = 0;
  }
  for(int i=1; i<=m; i++) {
  	ll u, v, len;
  	cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
  	ll u = 1, v, len;
  	cin >> v >> len;
  	e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
  	 ll x = a[i].v;
  	 ll y = a[i].len;
  	 if(y > dis[x])  ans++;
  	 else if(y == dis[x] && cnt[x] > 1) {
  	 	ans++;
  	 	cnt[x]--;
  	 }
  }
  printf("%d\n", ans);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {
    }
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  q.push(make_pair(0, 1));
  while(!q.empty()) {
    pii p = q.top();
    q.pop();
    ll u = p.second;
    if(vis[u])  continue;
    vis[u] = 1;
    for(int i=0; i<e[u].size(); i++) {
        Edge x = e[u][i];
        if(dis[x.v] > dis[u] + x.len) {
            cnt[x.v] = cnt[u];
            //if(cnt[x.v] > 1e8) cnt[x.v] = 1e8;
            dis[x.v] = dis[u] + x.len;
            q.push(make_pair(dis[x.v], x.v));
        }
        else if(dis[x.v] == dis[u] + x.len)
            cnt[x.v] += cnt[u];
            if(cnt[x.v > 1e8]) cnt[x.v] = 1e8;
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
    dis[i] = inf;
    vis[i] =  0;
    cnt[i] = 0;
  }
  for(int i=1; i<=m; i++) {
    ll u, v, len;
    cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
    ll u = 1, v, len;
    cin >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
     ll x = a[i].v;
     ll y = a[i].len;
     if(y > dis[x])  ans++;
     else if(y == dis[x] && cnt[x] > 1) {
        ans++;
        cnt[x]--;
     }
  }
  printf("%d\n", ans);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {
    }
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  q.push(make_pair(0, 1));
  while(q.size()) {
    pii p = q.top();
    q.pop();
    ll u = p.second;
    if(vis[u])  continue;
    vis[u] = 1;
    for(int i=0; i<e[u].size(); i++) {
        Edge x = e[u][i];
        if(dis[x.v] > dis[u] + x.len) {
            cnt[x.v] = cnt[u];
            if(cnt[x.v] > 1e6) cnt[x.v] = 1e5;
            dis[x.v] = dis[u] + x.len;
            q.push(make_pair(dis[x.v], x.v));
        }
        else if(dis[x.v] == dis[u] + x.len)
            cnt[x.v] += cnt[u];
            if(cnt[x.v > 1e6]) cnt[x.v] = 1e5;
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
    dis[i] = inf;
    vis[i] =  0;
    cnt[i] = 0;
  }
  for(int i=1; i<=m; i++) {
    ll u, v, len;
    cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
    ll u = 1, v, len;
    cin >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
     ll x = a[i].v;
     ll y = a[i].len;
     if(y > dis[x])  ans++;
     else if(y == dis[x] && cnt[x] > 1) {
        ans++;
        cnt[x]--;
     }
  }
  printf("%d\n", ans);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {}
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  while(q.size())  q.pop();
  q.push(make_pair(0, 1));
  while(!q.empty()) {
    pii p = q.top();
    q.pop();
    ll u = p.second;
    if(vis[u])  continue;
    vis[u] = 1;
    for(int i=0; i<e[u].size(); i++) {
        Edge x = e[u][i];
        if(dis[x.v] > dis[u] + x.len) {
            cnt[x.v] = cnt[u];
            //if(cnt[x.v] > 1e8) cnt[x.v] = 1e8;
            dis[x.v] = dis[u] + x.len;
            q.push(make_pair(dis[x.v], x.v));
        }
        else if(dis[x.v] == dis[u] + x.len) {
            cnt[x.v] += cnt[u];
            if(cnt[x.v > 1e8]) cnt[x.v] = 1e8;
        }
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
    dis[i] = inf;
    vis[i] =  0;
    cnt[i] = 0;
    e[i].clear();
  }
  a.clear();
  for(int i=1; i<=m; i++) {
    ll u, v, len;
    cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
    ll u = 1, v, len;
    cin >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
     ll x = a[i].v;
     ll y = a[i].len;
     if(y > dis[x])  ans++;
     else if(y == dis[x] && cnt[x] > 1) {
        ans++;
        cnt[x]--;
     }
  }
  printf("%d\n", ans);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

typedef __int64 ll;
typedef pair<ll, ll> pii;
const ll inf = 1LL << 60;

struct Edge {
  ll v, len;
  Edge (ll v, ll len) :
    v(v), len(len) {
    }
};
priority_queue <pii, vector<pii>, greater<pii> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
int n, m, k;
bool vis[100010];
void dijkstra() {
  //vis[1] = 1;
  dis[1] = 0;
  cnt[1] = 1;
  q.push(make_pair(0, 1));
  while(q.size()) {
    pii p = q.top();
    q.pop();
    ll u = p.second;
    if(vis[u])  continue;
    vis[u] = 1;
    for(int i=0; i<e[u].size(); i++) {
        Edge x = e[u][i];
        if(dis[x.v] > dis[u] + x.len) {
            cnt[x.v] = cnt[u];
            //if(cnt[x.v] > 1e8) cnt[x.v] = 1e8;
            dis[x.v] = dis[u] + x.len;
            q.push(make_pair(dis[x.v], x.v));
        }
        else if(dis[x.v] == dis[u] + x.len)
            cnt[x.v] += cnt[u];
            if(cnt[x.v > 1e8]) cnt[x.v] = 1e8;
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for(int i=1; i<=n; i++) {
    dis[i] = inf;
    vis[i] =  0;
    cnt[i] = 0;
  }
  for(int i=1; i<=m; i++) {
    ll u, v, len;
    cin >> u >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
  }
  for(int i=1; i<=k; i++) {
    ll u = 1, v, len;
    cin >> v >> len;
    e[u].push_back(Edge(v, len));
    e[v].push_back(Edge(u, len));
    a.push_back(Edge(v, len));
  }
  dijkstra();
  int ans = 0;
  for(int i=0; i<a.size(); i++) {
     ll x = a[i].v;
     ll y = a[i].len;
     if(y > dis[x])  ans++;
     else if(y == dis[x] && cnt[x] > 1) {
        ans++;
        cnt[x]--;
     }
  }
  printf("%d\n", ans);
  return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	vector<long long>dist;
	priority_queue<distType> distQueue;

	for(int i = 0;i <= n;i++)
	{
		dist[i] = -1;
		if (trainCost[i] > 0)
			distQueue.push(distType(i, trainCost[i]));
	}
	dist[0] = 0;

	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
			dist[minPoint] = minDist;
		else
		{
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;

struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else if (a.dist == b.dist)
            return a.index > b.index;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    distQueue.push(distType(0, 0));

    dist.resize(n + 1);
    for(int i = 0;i <= n;i++)
        dist[i] = -1;

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        dist[minPoint] = minDist;
        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];

            if (trainCost[graph[minPoint][j]] >= newDist)
                removeTrain[graph[minPoint][j]] = 1;

			if (dist[graph[minPoint][j]] > newDist || dist[graph[minPoint][j]] == -1)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], newDist));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 1;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(int src, int n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<int> found;
	for(int i = 0;i <= n;i++)
		found.push_back(0);
	found[src] = 1;
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	int ff = 0;
	while(!distQueue.empty())
	{
		ff++;
		if (ff > 3000000)
			cout << ff << endl;
		long long minDist = -1;
		long long minPoint = -1;
		minDist = distQueue.front().dist;
		minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;

		dist[minPoint] = minDist;
		if (trainCost[minPoint] < minDist)
		{
			int updated = 0;
			for(int j = 0;j < graph[src].size();j++)
				if (graph[src][j] == minPoint)
				{
					cost[src][j] = trainCost[minPoint];
					updated = 1;

					for(int k = 0;k < graph[minPoint].size();k++)
						if (graph[minPoint][k] == src)
						{
							cost[minPoint][k] = trainCost[minPoint];
							break;
						}
					break;
				}
			if (!updated)
			{
				graph[src].push_back(minPoint);
				cost[src].push_back(trainCost[minPoint]);
				graph[minPoint].push_back(src);
				cost[minPoint].push_back(trainCost[minPoint]);
			}
		}
		else
			removeTrain[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
		found[minPoint] = 1;
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(int i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		if (dist[minPoint] != -1)
			continue;

		dist[minPoint] = minDist > trainCost[minPoint] ? trainCost[minPoint] : minDist;
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;
		}
		else
		{
			if (minDist < dist[minPoint])
			{
				cout << minPoint << endl;
				cout << minDist << " " << dist[minPoint] << endl;
				while(1);
			}
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(int src, int n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<int> found;
	for(int i = 0;i <= n;i++)
		found.push_back(0);
	found[src] = 1;
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	int ff = 0;
	while(!distQueue.empty())
	{
		ff++;
		if (ff > m)
			cout << ff << endl;
		long long minDist = -1;
		long long minPoint = -1;
		minDist = distQueue.front().dist;
		minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;

		dist[minPoint] = minDist;
		if (trainCost[minPoint] < minDist)
		{
			int updated = 0;
			for(int j = 0;j < graph[src].size();j++)
				if (graph[src][j] == minPoint)
				{
					cost[src][j] = trainCost[minPoint];
					updated = 1;

					for(int k = 0;k < graph[minPoint].size();k++)
						if (graph[minPoint][k] == src)
						{
							cost[minPoint][k] = trainCost[minPoint];
							break;
						}
					break;
				}
			if (!updated)
			{
				graph[src].push_back(minPoint);
				cost[src].push_back(trainCost[minPoint]);
				graph[minPoint].push_back(src);
				cost[minPoint].push_back(trainCost[minPoint]);
			}
		}
		else
			removeTrain[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
		found[minPoint] = 1;
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(int i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;

		}
		else
		{
			if (minDist < dist[minPoint])
				while(1);
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			if (dist[graph[minPoint][j]] == -1 || dist[graph[minPoint][j]] > newDist)
				distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(int src, int n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<int> found;
	for(int i = 0;i <= n;i++)
		found.push_back(0);
	found[src] = 1;
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	int ff = 0;
	while(!distQueue.empty())
	{
		ff++;
		if (ff > 3000000)
		{
			cout << ff << endl;
			break;
		}
		long long minDist = -1;
		long long minPoint = -1;
		minDist = distQueue.front().dist;
		minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;

		dist[minPoint] = minDist;
		if (trainCost[minPoint] < minDist)
		{
			int updated = 0;
			for(int j = 0;j < graph[src].size();j++)
				if (graph[src][j] == minPoint)
				{
					cost[src][j] = trainCost[minPoint];
					updated = 1;

					for(int k = 0;k < graph[minPoint].size();k++)
						if (graph[minPoint][k] == src)
						{
							cost[minPoint][k] = trainCost[minPoint];
							break;
						}
					break;
				}
			if (!updated)
			{
				graph[src].push_back(minPoint);
				cost[src].push_back(trainCost[minPoint]);
				graph[minPoint].push_back(src);
				cost[minPoint].push_back(trainCost[minPoint]);
			}
		}
		else
			removeTrain[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
		found[minPoint] = 1;
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(int i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;
		}
		else
		{
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			if (minDist >= dist[minPoint])
				continue;
			else
				dist[minPoint] = minDist;
		}

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			if (newDist <= dist[graph[minPoint][j]] || dist[graph[minPoint][j]] == -1)
				distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else if (a.dist == b.dist)
            return a.index > b.index;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));

    for(int i = 0;i < graph[src].size();i++)
        distQueue.push(distType(graph[src][i], cost[src][i]));
    dist.resize(n + 1);
    dist[0] = 0;
    for(int i = 0;i <= n;i++)
        dist[i] = -1;

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;
    visit[0] = 1;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

        dist[minPoint] = minDist;
        if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist || dist[graph[minPoint][j]] == -1)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], newDist));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;

		}
		else
		{
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;

struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else if (a.dist == b.dist)
            return a.index > b.index;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    distQueue.push(distType(0, 0));

    dist.resize(n + 1);
    for(int i = 0;i <= n;i++)
        dist[i] = -1;

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

    //    cout << minPoint << " " << minDist << endl;
        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        dist[minPoint] = minDist;
        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];

          //  if (graph[minPoint][j] == 2 && minPoint == 1)
          //      cout << "fdsafd" << newDist << endl;
            if (trainCost[graph[minPoint][j]] >= newDist)
            {
                removeTrain[graph[minPoint][j]] = 1;
            //    cout << minPoint << " " << graph[minPoint][j] << endl;
            }
            if (dist[graph[minPoint][j]] > newDist || dist[graph[minPoint][j]] == -1)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], newDist));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 1;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	vector<long long>dist;
	priority_queue<distType> distQueue;

	for(int i = 0;i <= n;i++)
	{
		dist.push_back(trainCost[i]);
		if (trainCost[i] > 0)
			distQueue.push(distType(i, trainCost[i]));
	}

	for(int i = 0;i < graph[src].size();i++)
	{
		distQueue.push(distType(graph[src][i], cost[src][i]));
		if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
			dist[graph[src][i]] = cost[src][i];
	}

	vector<int> visit;
	visit.resize(n + 1);
	for(int i = 0;i <= n;i++)
		visit[i] = 0;
	visit[src] = 1;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		dist[minPoint] = minDist;
		if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;

		if (visit[minPoint])
			continue;
		visit[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			if (dist[graph[minPoint][j]] >= newDist || dist[graph[minPoint][j]] == -1)
				distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
    {
        if (trainCost[i] > 0)
            dist.push_back(trainCost[i]);
        else
            dist.push_back(1e18);
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    }
    dist[0] = 0;
    distQueue.push(distType(0, 0));
    /*
    for(int i = 0;i < graph[src].size();i++)
    {
        if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
            dist[graph[src][i]] = cost[src][i];
    }
    */

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

     //   cout << minPoint << " " << minDist << endl;
        if (visit[minPoint] == 1)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist)
            {
                distQueue.push(distType(graph[minPoint][j], newDist));
                dist[graph[minPoint][j]] = newDist;
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
      /*  for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
            */
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));

    for(int i = 0;i < graph[src].size();i++)
        distQueue.push(distType(graph[src][i], cost[src][i]));
    dist.resize(n + 1);
    dist[0] = 0;
    for(int i = 0;i <= n;i++)
        dist[i] = -1;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

        dist[minPoint] = minDist;
        if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist || dist[graph[minPoint][j]] == -1)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], newDist));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;
		}
		else
		{
			if (minDist < dist[minPoint])
				cout << "fffffff" << endl;
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			if (dist[graph[minPoint][j]] == -1 || dist[graph[minPoint][j]] > newDist)
				distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
    {
        if (trainCost[i] > 0)
            dist.push_back(trainCost[i]);
        else
            dist.push_back(1e18);
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    }
    dist[0] = 0;
    distQueue.push(distType(0, 0));
    /*
    for(int i = 0;i < graph[src].size();i++)
    {
        if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
            dist[graph[src][i]] = cost[src][i];
    }
    */

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

     //   cout << minPoint << " " << minDist << endl;
        if (visit[minPoint] == 1)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = minDist + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], dist[graph[minPoint][j]]));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
      /*  for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
            */
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
    {
        if (trainCost[i] > 0)
            dist.push_back(trainCost[i]);
        else
            dist.push_back(1e18);
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    }
    dist[0] = 0;
    distQueue.push(distType(0, 0));
    /*
    for(int i = 0;i < graph[src].size();i++)
    {
        if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
            dist[graph[src][i]] = cost[src][i];
    }
    */

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

     //   cout << minPoint << " " << minDist << endl;
        if (visit[minPoint] == 1)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist)
            {
                distQueue.push(distType(graph[minPoint][j], newDist));
                dist[graph[minPoint][j]] = newDist;
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	vector<long long>dist;
	priority_queue<distType> distQueue;

	for(int i = 0;i <= n;i++)
	{
		dist.push_back(trainCost[i]);
		if (trainCost[i] > 0)
			distQueue.push(distType(i, trainCost[i]));
	}

	for(int i = 0;i < graph[src].size();i++)
	{
		distQueue.push(distType(graph[src][i], cost[src][i]));
		if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
			dist[graph[src][i]] = cost[src][i];
	}

	vector<int> visit;
	visit.resize(n + 1);
	for(int i = 0;i <= n;i++)
		visit[i] = 0;
	visit[src] = 1;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
			dist[minPoint] = minDist;
		if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		if (visit[minPoint])
			continue;
		visit[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	vector<long long>dist;
	priority_queue<distType> distQueue;

	for(int i = 0;i <= n;i++)
	{
		dist.push_back(trainCost[i]);
		if (trainCost[i] > 0)
			distQueue.push(distType(i, trainCost[i]));
	}

	for(int i = 0;i < graph[src].size();i++)
	{
		distQueue.push(distType(graph[src][i], cost[src][i]));
		if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
			dist[graph[src][i]] = cost[src][i];
	}

	vector<int> visit;
	visit.resize(n + 1);
	for(int i = 0;i <= n;i++)
		visit[i] = 0;
	visit[src] = 1;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
			dist[minPoint] = minDist;
		else
		{
			if (visit[minPoint] == 1 && trainCost[minPoint] >= dist[minPoint])
				removeTrain[minPoint] = 1;
			if (minDist >= dist[minPoint])
				continue;
		}
		if (visit[minPoint])
			continue;
		visit[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
    {
        dist.push_back(trainCost[i]);
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    }

    for(int i = 0;i < graph[src].size();i++)
    {
        distQueue.push(distType(graph[src][i], cost[src][i]));
        if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
            dist[graph[src][i]] = cost[src][i];
    }

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;
    visit[src] = 1;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

        dist[minPoint] = minDist;
        if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist || dist[graph[minPoint][j]] == -1)
                distQueue.push(distType(graph[minPoint][j], newDist));
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	vector<long long>dist;
	priority_queue<distType> distQueue;

	for(int i = 0;i <= n;i++)
	{
		dist.push_back(trainCost[i]);
		if (trainCost[i] > 0)
			distQueue.push(distType(i, trainCost[i]));
	}

	for(int i = 0;i < graph[src].size();i++)
	{
		distQueue.push(distType(graph[src][i], cost[src][i]));
		if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
			dist[graph[src][i]] = cost[src][i];
	}

	vector<int> visit;
	visit.resize(n + 1);
	for(int i = 0;i <= n;i++)
		visit[i] = 0;
	visit[src] = 1;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
			dist[minPoint] = minDist;
		else
		{
			if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			if (dist[minPoint] < minDist)
				continue;
			if (dist[minPoint] > minDist)
				dist[minPoint] = minDist;
		}
		if (visit[minPoint])
			continue;
		visit[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));

    for(int i = 0;i < graph[src].size();i++)
        distQueue.push(distType(graph[src][i], cost[src][i]));
    dist.resize(n + 1);
    dist[0] = 0;
    for(int i = 0;i <= n;i++)
        dist[i] = -1;

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;
    visit[0] = 1;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

        dist[minPoint] = minDist;
        if (visit[minPoint] == 1 && trainCost[minPoint] >= minDist)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = dist[minPoint] + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist || dist[graph[minPoint][j]] == -1)
            {
                dist[graph[minPoint][j]] = newDist;
                distQueue.push(distType(graph[minPoint][j], newDist));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
        for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		if (minDist < 0)
			while(1);
		dist[minPoint] = minDist;
		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		else if (trainCost[minPoint] != -1 && trainCost[minPoint] < dist[minPoint])
			dist[minPoint] = trainCost[minPoint];

		for(long long j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
/*		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
*/
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist > b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(trainCost[i]);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1)
			{
				if (minDist > trainCost[minPoint])
					minDist = trainCost[minPoint];
				else
					removeTrain[minPoint] = 1;
			}
			dist[minPoint] = minDist;
		}
		else
		{
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}

		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		if (dist[minPoint] != -1)
			continue;

		if (trainCost[minPoint] != -1)
			dist[minPoint] = minDist > trainCost[minPoint] ? trainCost[minPoint] : minDist;
		else
			dist[minPoint] = minDist;
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (long long in, int d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(int src, int n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<int> found;
	for(int i = 0;i <= n;i++)
		found.push_back(0);
	found[src] = 1;
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = -1;
		long long minPoint = -1;
		minDist = distQueue.front().dist;
		minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		dist[minPoint] = minDist;
		if (trainCost[minPoint] < minDist)
		{
			int updated = 0;
			for(int j = 0;j < graph[src].size();j++)
				if (graph[src][j] == minPoint)
				{
					cost[src][j] = trainCost[minPoint];
					updated = 1;

					for(int k = 0;k < graph[minPoint].size();k++)
						if (graph[minPoint][k] == src)
						{
							cost[minPoint][k] = trainCost[minPoint];
							break;
						}
					break;
				}
			if (!updated)
			{
				graph[src].push_back(minPoint);
				cost[src].push_back(trainCost[minPoint]);
				graph[minPoint].push_back(src);
				cost[minPoint].push_back(trainCost[minPoint]);
			}
		}
		else
			removeTrain[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
		found[minPoint] = 1;
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(int i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1 && minDist > trainCost[minPoint])
				minDist = trainCost[minPoint];
			dist[minPoint] = minDist;
		}
		else
		{
			if (trainCost[minPoint] >= minDist)
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}