Problem:
Problem J:
Merry Christmas
International Christmas Present Company (ICPC) is a company to employ Santa and deliver
presents on Christmas. Many parents request ICPC to deliver presents to their children at
specified time of December 24. Although same Santa can deliver two or more presents, because
it takes time to move between houses, two or more Santa might be needed to finish all the
requests on time.
Employing Santa needs much money, so the president of ICPC employed you, a great program-
mer, to optimize delivery schedule. Your task is to write a program to calculate the minimum
number of Santa necessary to finish the given requests on time. Because each Santa has been
well trained and can conceal himself in the town, you can put the initial position of each Santa
anywhere.
Input
The input consists of several datasets. Each dataset is formatted as follows.
N M L
u
1
v
1
d
1
u
2
v
2
d
2
.
.
.
u
M
v
M
d
M
p
1
t
1
p
2
t
2
.
.
.
p
L
t
L
The first line of a dataset contains three integer,
N
,
M
and
L
(1 ≤
N
≤ 100, 0 ≤
M
≤ 1000,
1 ≤
L
≤ 1000) each indicates the number of houses, roads and requests respectively.
The following
M
lines describe the road network. The
i
-th line contains three integers,
u
i
,
v
i
,
and
d
i
(0 ≤
u
i
<
v
i
≤
N
- 1, 1 ≤
d
i
≤ 100) which means that there is a road connecting houses
u
i
and
v
i
with
d
i
length. Each road is bidirectional. There is at most one road between same
pair of houses. Whole network might be disconnected.
The next
L
lines describe the requests. The
i
-th line contains two integers,
p
i
and
t
i
(0 ≤
p
i
≤
N
- 1, 0 ≤
t
i
≤ 10
8
) which means that there is a delivery request to house
p
i
on time
t
i
. There
is at most one request for same place and time. You can assume that time taken other than
movement can be neglectable, and every Santa has the same speed, one unit distance per unit
time.
The end of the input is indicated by a line containing three zeros separated by a space, and you
should not process this as a test case.
Output
Print the minimum number of Santa necessary to finish all the requests on time.
Sample Input
3 2 3
0 1 10
1 2 10
0 0
1 10
2 0
3 2 4
0 1 10
1 2 10
0 0
1 10
2 20
0 40
10 10 10
0 1 39
2 3 48
3 5 20
4 8 43
3 9 10
8 9 40
3 4 5
5 7 20
1 7 93
1 3 20
0 0
1 100000000
2 100
3 543
4 500
5 400
6 300
7 200
8 100
9 100
0 0 0
Output for the Sample Input
2
1
4

Submitted solutions:

code_snippet: #include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

typedef int ll;
const int inf = 200000000;
#define N 2100
int lef[1005], pn;
int tim, T[1005];
vector<int> G[1005];
bool match(int x){
    for(int i = 0; i < G[x].size(); i++)
    {
        int v = G[x][i];
        if(tim != T[v])
        {
            T[v] = tim;
            if(lef[v]==-1 || match(lef[v]))
            {
                lef[v] = x;
                return true;
            }
        }
    }
    return false;
}
int work(){
    int ans = 0;
    memset(lef, -1, sizeof lef);
    tim = 1;
    memset(T, 0, sizeof T);
    for(int i = 1; i <= pn; i++)
    {
        tim++;
        if(match(i))ans++;
    }
    return ans;
}
int dis[105][105], a[1005], b[1005];
int n, m, L;
int solve(){
    pn = L;
    for(int i = 1; i <= L; i++) G[i].clear();
    for(int i = 1; i <= L; i++)
    {
        for(int j = 1; j <= L; j++)
        if(i!=j && b[i] + dis[a[i]][a[j]] <= b[j])
        {
            G[i].push_back(j);
        }
    }
	return L - work();
}
int main(){
	while(scanf("%d %d %d", &n, &m, &L), n+m+L){
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                if(i!=j)
                    dis[i][j] = dis[j][i] = inf;
                else dis[i][j] = dis[j][i] = 0;
        while(m--){
            int u, v, d;scanf("%d %d %d", &u, &v, &d);
            dis[u][v] = dis[v][u] = min(dis[u][v], d);
        }
        for(int k = 0; k < n; k++)
            for(int i = 0; i < n; i++)if(i!=k)
                for(int j = 0; j < n; j++)if(i!=j && j!=k)
                    dis[j][i] = dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
        for(int i = 1; i <= L; i++)scanf("%d %d", &a[i], &b[i]);
   //     puts("--");
        printf("%d\n",solve());
	}
	return 0;
}
/*


*/



/*
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

typedef int ll;
const int inf = 1000000;
#define N 10100
char c[105][105], way[1005];
int go[300], step[1005], top;
int mp[105][105], v[12], num;
int hpinit, hpmax, n, m, dp[2][1<<12];

bool solve(){
	int cur = 0;
	memset(dp[cur], 0, sizeof dp[cur]);
	for(int j = (1<<num)-1; j >= 0; j--)
	{
		int now = hpinit;
		for(int k = 0; k < num; k++)
			if((j & (1<<k))==0)
				now += v[k];
		dp[cur][j] = min(now, hpmax);
	}
	int x = 1, y = 1;
	for(int i = 1; i <= top; i++)
	{
		cur ^= 1;
		memset(dp[cur], 0, sizeof dp[cur]);
		if(way[i]=='U') x -= step[i];
		else if(way[i]=='D') x += step[i];
		else if(way[i]=='L') y -= step[i];
		else y += step[i];
		for(int j = (1<<num)-1; j >= 0; j--)
			if(dp[cur^1][j])
			{
				int now = dp[cur^1][j] - mp[x][y];
				dp[cur][j] = max(dp[cur][j], now);
				for(int k = 0; k < num; k++)
					if(j & (1<<k))
						dp[cur][j & (~(1<<k))] = max(dp[cur][j & (~(1<<k))], min(now+v[k], hpmax));
			}
	}
	for(int j = (1<<num)-1; j >= 0; j--)
		if(dp[cur][j])return true;
	return false;
}
void input(){
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++)
		scanf("%s", c[i]+1);
	int tmp, val; scanf("%d", &tmp);
	char s[3];
	while(tmp--){
		scanf("%s %d", s, &val);
		go[s[0]] = val;
	}
	scanf("%d", &top);
	for(int i = 1; i <= top; i++) {
		scanf("%s %d", s, &step[i]);
		way[i] = s[0];
	}
	scanf("%d", &num);
	for(int i = 0; i < num; i++)scanf("%d", &v[i]);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			mp[i][j] = go[c[i][j]];
}
int main(){
	while(scanf("%d %d", &hpinit, &hpmax), hpinit + hpmax){
		input();
		solve() ? puts("YES"):puts("NO");
	}
	return 0;
}
/*


*/
accuracy: 1
time_ms: 550
memory_kb: 7640
final_rank: 8

code_snippet: #include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

typedef int ll;
const int inf = 200000000;
#define N 2100
int lef[1005], pn;
int tim, T[1005];
vector<int> G[1005];
bool match(int x){
    for(int i = 0; i < G[x].size(); i++)
    {
        int v = G[x][i];
        if(tim != T[v])
        {
            T[v] = tim;
            if(lef[v]==-1 || match(lef[v]))
            {
                lef[v] = x;
                return true;
            }
        }
    }
    return false;
}
int work(){
    int ans = 0;
    memset(lef, -1, sizeof lef);
    tim = 1;
    memset(T, 0, sizeof T);
    for(int i = 1; i <= pn; i++)
    {
        tim++;
        if(match(i))ans++;
    }
    return ans;
}
int dis[105][105], a[1005], b[1005];
int n, m, L;
int solve(){
    pn = L;
    for(int i = 1; i <= L; i++) G[i].clear();
    for(int i = 1; i <= L; i++)
    {
        for(int j = 1; j <= L; j++)
        if(i!=j && b[i] + dis[a[i]][a[j]] <= b[j])
        {
            G[i].push_back(j);
        }
    }
	return L - work();
}
int main(){
	while(scanf("%d %d %d", &n, &m, &L), n+m+L){
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                if(i!=j)
                    dis[i][j] = dis[j][i] = inf;
                else dis[i][j] = dis[j][i] = 0;
        while(m--){
            int u, v, d;scanf("%d %d %d", &u, &v, &d);
            dis[u][v] = dis[v][u] = min(dis[u][v], d);
        }
        for(int k = 0; k < n; k++)
            for(int i = 0; i < n; i++)if(i!=k)
                for(int j = 0; j < n; j++)if(i!=j && j!=k)
                    dis[j][i] = dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
        for(int i = 1; i <= L; i++)scanf("%d %d", &a[i], &b[i]);
   //     puts("--");
        printf("%d\n",solve());
	}
	return 0;
}
/*


*/



/*
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

typedef int ll;
const int inf = 1000000;
#define N 10100
char c[105][105], way[1005];
int go[300], step[1005], top;
int mp[105][105], v[12], num;
int hpinit, hpmax, n, m, dp[2][1<<12];

bool solve(){
	int cur = 0;
	memset(dp[cur], 0, sizeof dp[cur]);
	for(int j = (1<<num)-1; j >= 0; j--)
	{
		int now = hpinit;
		for(int k = 0; k < num; k++)
			if((j & (1<<k))==0)
				now += v[k];
		dp[cur][j] = min(now, hpmax);
	}
	int x = 1, y = 1;
	for(int i = 1; i <= top; i++)
	{
		cur ^= 1;
		memset(dp[cur], 0, sizeof dp[cur]);
		if(way[i]=='U') x -= step[i];
		else if(way[i]=='D') x += step[i];
		else if(way[i]=='L') y -= step[i];
		else y += step[i];
		for(int j = (1<<num)-1; j >= 0; j--)
			if(dp[cur^1][j])
			{
				int now = dp[cur^1][j] - mp[x][y];
				dp[cur][j] = max(dp[cur][j], now);
				for(int k = 0; k < num; k++)
					if(j & (1<<k))
						dp[cur][j & (~(1<<k))] = max(dp[cur][j & (~(1<<k))], min(now+v[k], hpmax));
			}
	}
	for(int j = (1<<num)-1; j >= 0; j--)
		if(dp[cur][j])return true;
	return false;
}
void input(){
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++)
		scanf("%s", c[i]+1);
	int tmp, val; scanf("%d", &tmp);
	char s[3];
	while(tmp--){
		scanf("%s %d", s, &val);
		go[s[0]] = val;
	}
	scanf("%d", &top);
	for(int i = 1; i <= top; i++) {
		scanf("%s %d", s, &step[i]);
		way[i] = s[0];
	}
	scanf("%d", &num);
	for(int i = 0; i < num; i++)scanf("%d", &v[i]);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			mp[i][j] = go[c[i][j]];
}
int main(){
	while(scanf("%d %d", &hpinit, &hpmax), hpinit + hpmax){
		input();
		solve() ? puts("YES"):puts("NO");
	}
	return 0;
}
/*


*/
accuracy: 1
time_ms: 550
memory_kb: 7508
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#include <bit>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using i128 = __int128_t;
using pii = pair<int, int>;
using pic = pair<int, char>;
using pci = pair<char, int>;
using pll = pair<ll, ll>;
using pllc = pair<ll, char>;
#define rep(i, a, n) for (int i = a; i < (n); i++)

// ===== プロトタイプ宣言 =====
int solve();

// ===== main関数 =====
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  return solve();
}


void prvec(vector<string> V) {
  for (const auto& v : V)
    cout << v << endl;
}

void prvec(vector<bool> V) {
  for (const auto& v : V)
    cout << boolalpha << setw(5) << setfill(' ') << v << " ";
  cout << endl;
}

template <typename T>
void prvec(vector<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(list<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(set<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(unordered_set<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(multiset<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T1>
void prvec(deque<T1> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

void prvec(set<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(deque<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(deque<pll> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pll> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(map<T1, T2> V) {
  for (const auto& [k, v] : V)
    cout << "{" << k << ": " << v << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(map<T1, pair<T2, T3>> V) {
  for (const auto& [k, v] : V)
    cout << k << " : {" << v.first << " " << v.second << "}" << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(map<T1, vector<pair<T2, T3>>> V) {
  for (const auto& [k, v] : V) {
    cout << k << " : " ;
    for (const auto& [a, b] : v)
      cout << "{" << a << ", " << b << "}, ";
    cout << endl;
  }
}

void prvec(map<int, bool> V) {
  for (const auto& [k, v] : V)
    cout << k << " : " << boolalpha << v << endl;
}

void prvec(map<string, pii> V) {
  for (const auto& [k, v] : V) 
    cout << k << " : " << v.first << " " << v.second << endl;
}

template <typename T>
void prvec(map<pii, T> V) {
  for (const auto& [k, v] : V) 
    cout << "{" << k.first << ", " << k.second << "}: " << v << endl;
}

void prvec(map<int, vector<int>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& v : vec) {
      cout << v << " ";
    }
    cout << endl;
  }
}

void prvec(map<char, vector<int>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& v : vec) {
      cout << v << " ";
    }
    cout << endl;
  }
}

void prvec(map<char, vector<pii>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& [a, b] : vec) {
      cout << "{" << a << ", " << b << "}, ";
    }
    cout << endl;
  }
}

void prvec(map<int, vector<pii>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& [a, b] : vec) {
      cout << "{" << a << ", " << b << "}, ";
    }
    cout << endl;
  }
}

void prvec(map<int, stack<int>> V) {
  for (const auto& [k, stk] : V) {
    cout << k << " : ";
    stack<int> stk2 = stk;
    while (!stk2.empty()) {
      int v = stk2.top(); stk2.pop();
      cout << v << " ";
    }
    cout << endl;
  }
}

template <typename T1, typename T2>
void prvec(vector<pair<T1, T2>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<string, string>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<double, int>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<double, double>> V) {
  for (const auto& [a, b] : V)
    cout << fixed << setprecision(15)  << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<char, int>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<int, char>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(unordered_map<T1, T2> V) {
  for (const auto& [k, v] : V)
    cout << "{" << k << ": " << v << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(set<pair<T1, T2>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<int, vector<int>>> V) {
  for (const auto& [a, vec] : V) {
    cout << a << " : ";
    for (const auto& v : vec) cout << v << " ";
    cout << endl;
  }
}

void prvec(vector<pair<int, set<int>>> V) {
  for (const auto& [a, st] : V) {
    cout << a << " : ";
    for (const auto& v : st) cout << v << " ";
    cout << endl;
  }
}

template <typename T1, typename T2, typename T3>
void prvec(vector<tuple<T1, T2, T3>> V) {
  for (const auto& [a, b, c] : V)
    cout << "{" << a << ", " << b << ", " << c << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(set<tuple<T1, T2, T3>> V) {
  for (const auto& [a, b, c] : V)
    cout << "{" << a << ", " << b << ", " << c << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3, typename T4>
void prvec(vector<tuple<T1, T2, T3, T4>> V) {
  for (const auto& [a, b, c, d] : V)
    cout << "{" << a << ", " << b << ", " << c << ", " << d << "}, ";
  cout << endl;
}

class UnionFind {
  private :
    vector<int> parent;
    vector<int> size;
  
  public :
    UnionFind(int n) : parent(n), size(n, 1) {
      for (int i = 0; i < n; i++) parent[i] = i;
    }
    
    int find(int x) {
      if (parent[x] == x) return x;
      return parent[x] = find(parent[x]);
    }
    
    bool unite(int x, int y) {
      int rootX = find(x);
      int rootY = find(y);
      if (rootX == rootY) return false; // cycle検出
      
      if (size[rootX] < size[rootY]) swap(rootX, rootY);
      parent[rootY] = rootX;
      size[rootX] += size[rootY];
      return true;
    }
    
    int getSize(int x) {
      return size[find(x)];
    }
    
    bool same(int x, int y) {
      return find(x) == find(y);
    }
};

template <class Abel>
// 重み付きUnionFindの定義
struct WeightedUnionFind {
  vector<int> parent, size;
  vector<Abel> diff_weight;

  WeightedUnionFind(int n)
    : parent(n), size(n, 1), diff_weight(n, 0) {
    iota(parent.begin(), parent.end(), 0);
  }

  int find(int x) {
    if (parent[x] == x) return x;
    int r = find(parent[x]);
    diff_weight[x] += diff_weight[parent[x]];
    return parent[x] = r;
  }

  Abel weight(int x) {
    find(x);
    return diff_weight[x];
  }

  bool unite(int u, int v, ll w) {
    Abel wu = weight(u), wv = weight(v);
    int ru = find(u), rv = find(v);
    if (ru == rv) {
      return (wv - wu == w); // すでに矛盾ないかチェック
    }

    Abel dw = w + wu - wv;

    // union by size（大きいほうに小さいほうをつける）
    if (size[ru] < size[rv]) {
      swap(ru, rv);
      swap(u, v);
      dw = -dw;
    }

    parent[rv] = ru;
    diff_weight[rv] = dw;
    size[ru] += size[rv];
    return true;
  }

  bool same(int x, int y) {
    return find(x) == find(y);
  }

  Abel diff(int x, int y) {
    return weight(y) - weight(x);
  }
};

// **Binary Indexed Tree (Fenwick Tree)**
// 1-indexed
template <typename T>
struct FenwickTree {
  int size;
  vector<T> BIT;
  
  FenwickTree(int n) {
    size = n;
    BIT.assign(n + 1, 0);
  }
  
  void add(int idx, T val) {
    while (idx <= size) {
      BIT[idx] += val;
      idx += idx & -idx;
    }
  }
  
  T sum(int idx) {
    T s = 0;
    while (idx > 0) {
      s += BIT[idx];
      idx -= (idx & -idx);
    }
    return s;
  }
  
  T range_sum(int l, int r) {
    return sum(r) - sum(l - 1);
  }
};

// modint: mod計算をintを扱うように扱える構造体
// https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a#8-modint
template<int MOD> struct Fp {
  ll val;
  constexpr Fp(ll v = 0) noexcept : val(v % MOD) {
    if (val < 0) val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator - () const noexcept {
    return val ? MOD - val : 0;
  }
  constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r;}
  constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r;}
  constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r;}
  constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r;}
  constexpr Fp& operator += (const Fp& r) noexcept {
    val += r.val;
    if (val >= MOD) val -= MOD;
    return *this;
  }
  constexpr Fp& operator -= (const Fp& r) noexcept {
    val -= r.val;
    if (val < 0) val += MOD;
    return *this;
  }
  constexpr Fp& operator *= (const Fp& r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp& operator /= (const Fp& r) noexcept {
    return *this *= modpow(r, MOD - 2);
    // cout << "here" << endl;
    // ll a = r.val, b = MOD, u = 1, v = 0;
    // while (b) {
    //   ll t = a / b;
    //   a -= t * b; swap(a, b);
    //   u -= t * v; swap(u, v);
    // }
    // val = val * u % MOD;
    // if (val < 0) val += MOD;
    // return *this;
  }
  constexpr bool operator == (const Fp& r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator != (const Fp& r) const noexcept {
    return this->val != r.val;
  }
  constexpr bool operator < (const Fp& r) const noexcept { return this->val < r.val;}
  constexpr bool operator <= (const Fp& r) const noexcept { return this->val <= r.val;}
  constexpr bool operator > (const Fp& r) const noexcept { return this->val > r.val;}
  constexpr bool operator >= (const Fp& r) const noexcept { return this->val >= r.val;}
  friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) {
    return os << x.val;
  }
  friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) {
    ll v;
    is >> v;
    x = Fp<MOD>(v);
    return is;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, ll n) noexcept {
    if (n == 0) return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1) t = t * a;
    return t;
  }
};
using mint = Fp<998244353>;

int solve() {
  while (true) {
      int N, M, L;
      cin >> N >> M >> L;
      if (N == 0 && M == 0 && L == 0) break;
      
      const int INF = 1e9 + 7;
      vector<vector<int>> dist(N, vector<int>(N, INF));
      for (int i = 0; i < N; i++) dist[i][i] = 0;
      
      for (int i = 0; i < M; i++) {
        int u, v, d; cin >> u >> v >> d;
        dist[u][v] = dist[v][u] = min(dist[u][v], d);
      }
      
      for (int k = 0; k < N; k++) 
        for (int i = 0; i < N; i++) 
          for (int j = 0; j < N; j++)
            dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      
      vector<pii> requests(L);
      for (int i = 0; i < L; i++) {
        int t, p; cin >> p >> t;
        requests[i] = {t, p};
      }
    
    sort(requests.begin(), requests.end());
    
    vector<vector<int>> G(L);
    for (int i = 0; i < L; i++) {
      auto [ti, pi] = requests[i];
      for (int j = i + 1; j < L; j++) {
        auto [tj, pj] = requests[j];
        if (ti + dist[pi][pj] <= tj) G[i].push_back(j);
      }
    }
    
    vector<int> match(L, -1);
    vector<int> visited(L, false);
    
    auto dfs = [&](int from, auto&& self) -> bool {
      for (int to : G[from]) {
        if (visited[to]) continue;
        visited[to] = true;
        if (match[to] == -1 || self(match[to], self)) {
          match[to] = from;
          return true;
        }
      }
      return false;
    };
    
    int result = 0;
    for (int u = 0; u < L; u++) {
      visited.assign(L, false);
      if (dfs(u, dfs)) result++;
    }
    cout << L - result << endl;
  }
  
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 6144
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
using namespace std;
#define all(...) std::begin(__VA_ARGS__), std::end(__VA_ARGS__)
#define rall(...) std::rbegin(__VA_ARGS__), std::rend(__VA_ARGS__)
#define OVERLOAD_REP(_1, _2, _3, _4, name, ...) name
#define REP1(n) for(ll i=0;i<n;i++)
#define REP2(i, n) for (ll i=0;i<n;i++)
#define REP3(i, a, n) for (ll i=a;i<n;i++)
#define REP4(i, a, b, n) for(ll i=a;i<n;i+=b)
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_RREP(_1, _2, _3, _4, name, ...) name
#define RREP1(n) for(ll i=n;i>=0;i--)
#define RREP2(i, n) for(ll i=n;i>=0;i--)
#define RREP3(i, a, n) for(ll i=n;i>=a;i--)
#define RREP4(i, a, b, n) for(ll i=n;i>=a;i-=b)
#define rrep(...) OVERLOAD_RREP(__VA_ARGS__, RREP4, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define foa(a,v)  (auto& a : (v))
#define uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define len(n) (long long)(n).size()
#define pb push_back
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vs = vector<string>;
using vvs = vector<vs>;
using vvvs = vector<vvs>;
using vld = vector<ld>;
using vvld = vector<vld>;
using vvvld = vector<vvld>;
using vc = vector<char>;
using vvc = vector<vc>;
using vvvc = vector<vvc>;
using pll = pair<ll,ll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
template<class... T>
constexpr auto min(T... a){
    return min(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
constexpr auto max(T... a){
    return max(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
void input(T&... a){
    (cin >> ... >> a);
}
ll modpow(ll a,ll b,ll c){
    ll ans = 1;
    while (b){
        if (b & 1){
            ans *= a;
            ans %= c;
        }
        a *= a;
        a %= c;
        b /= 2;
    }
    return ans;
}
#define INT(...) int __VA_ARGS__; input(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; input(__VA_ARGS__)
#define CHA(...) char __VA_ARGS__; input(__VA_ARGS__)
#define VLL(name,length) vll name(length);rep(i,length){cin >> name[i];}
#define VVLL(name,h,w) vvll name(h,vll(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLL(name,a,b,c) vvvll name(a,vvll(b,vll(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VI(name,length) vi name(length);rep(i,length){cin >> name[i];}
#define VVI(name,h,w) vvi name(h,vi(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVI(name,a,b,c) vvvi name(a,vvll(b,vi(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VLD(name,length) vld name(length);rep(i,length){cin >> name[i];}
#define VVLD(name,h,w) vvld name(h,vld(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLD(name,a,b,c) vvvld name(a,vvld(b,vld(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VC(name,length) vc name(length);rep(i,length){cin >> name[i];}
#define VVC(name,h,w) vvc name(h,vc(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVC(name,a,b,c) vvvc name(a,vvc(b,vc(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VS(name,length) vs name(length);rep(i,length){cin >> name[i];}
#define VVS(name,h,w) vvs name(h,vs(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVS(name,a,b,c) vvvs name(a,vvs(b,vs(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define PLL(name) pll name;cin>>name.first>>name.second;
#define VPLL(name,length) vpll name(length);rep(i,length){cin>>name[i].first>>name[i].second;}
using mint = modint998244353;
void print(){cout << "\n";}
template<class T, class... Ts>
void print(const T& a, const Ts&... b){cout << a;(cout << ... << (cout << ' ', b));cout << '\n';}
void print(vll x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void print(vvi x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void print(vector<mint> x){rep(i,len(x)){cout << x[i].val();if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}


int main(){
    while(1){
        LL(n,m,l);
        if(n == 0){break;}
        vvpll edge(n);
        vvll dist(n,vll(n,1LL<<60));
        rep(i,n){
            dist[i][i] = 0;
        }
        rep(i,m){
            LL(u,v,d);
            edge[u].push_back({v,d});
            edge[v].push_back({u,d});
            dist[u][v] = min(dist[u][v],d);
            dist[v][u] = min(dist[v][u],d);
        }
        rep(k,n){
            rep(i,n){
                rep(j,n){
                    dist[i][j] = min(dist[i][j],dist[i][k] + dist[k][j]);
                }
            }
        }
        VPLL(a,l);
        mf_graph<ll> g(2*l+2);
        ll s = 2*l;
        ll t = 2*l+1;
        rep(i,l){
            g.add_edge(s,i,1);
            g.add_edge(i+l,t,1);
            rep(j,l){
                if(i == j){continue;}
                if(a[i].second + dist[a[i].first][a[j].first] <= a[j].second){
                    g.add_edge(i,j+l,1);
                }
            }
        }
        print(l - g.flow(s,t));

    }

}
accuracy: 1
time_ms: 290
memory_kb: 28284
final_rank: 14

code_snippet: // https://miscalc.hatenablog.com/entry/2022/11/11/213943#%E4%BE%8B%E9%A1%8C-2
#include <iostream>
#include <algorithm>
#include <vector>

#include <algorithm>

#include <vector>

namespace atcoder {

namespace internal {

template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <limits>
#include <queue>
#include <vector>

namespace atcoder {

template <class Cap> struct mf_graph {
  public:
    mf_graph() : _n(0) {}
    mf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        g[from].push_back(_edge{to, int(g[to].size()), cap});
        g[to].push_back(_edge{from, int(g[from].size()) - 1, 0});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
    };

    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result;
        for (int i = 0; i < m; i++) {
            result.push_back(get_edge(i));
        }
        return result;
    }
    void change_edge(int i, Cap new_cap, Cap new_flow) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        assert(0 <= new_flow && new_flow <= new_cap);
        auto& _e = g[pos[i].first][pos[i].second];
        auto& _re = g[_e.to][_e.rev];
        _e.cap = new_cap - new_flow;
        _re.cap = new_flow;
    }

    Cap flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    Cap flow(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);

        std::vector<int> level(_n), iter(_n);
        internal::simple_queue<int> que;

        auto bfs = [&]() {
            std::fill(level.begin(), level.end(), -1);
            level[s] = 0;
            que.clear();
            que.push(s);
            while (!que.empty()) {
                int v = que.front();
                que.pop();
                for (auto e : g[v]) {
                    if (e.cap == 0 || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    if (e.to == t) return;
                    que.push(e.to);
                }
            }
        };
        auto dfs = [&](auto self, int v, Cap up) {
            if (v == s) return up;
            Cap res = 0;
            int level_v = level[v];
            for (int& i = iter[v]; i < int(g[v].size()); i++) {
                _edge& e = g[v][i];
                if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                Cap d =
                    self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                if (d <= 0) continue;
                g[v][i].cap += d;
                g[e.to][e.rev].cap -= d;
                res += d;
                if (res == up) break;
            }
            return res;
        };

        Cap flow = 0;
        while (flow < flow_limit) {
            bfs();
            if (level[t] == -1) break;
            std::fill(iter.begin(), iter.end(), 0);
            while (flow < flow_limit) {
                Cap f = dfs(dfs, t, flow_limit - flow);
                if (!f) break;
                flow += f;
            }
        }
        return flow;
    }

    std::vector<bool> min_cut(int s) {
        std::vector<bool> visited(_n);
        internal::simple_queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            visited[p] = true;
            for (auto e : g[p]) {
                if (e.cap && !visited[e.to]) {
                    visited[e.to] = true;
                    que.push(e.to);
                }
            }
        }
        return visited;
    }

  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};

}  // namespace atcoder

#define rep(i, n) for(i = 0; i < n; i++)
using namespace std;
using namespace atcoder;
typedef pair<int, int> P;

const int INF = 1e+9;
int n, m, L;
int dist[100][100];

int main() {
	int i, j, k;

	while (cin >> n >> m >> L) {
		if (!n) break;
		rep(i, n) rep(j, n) dist[i][j] = INF;
		rep(i, n) dist[i][i] = 0;
		rep(i, m) {
			int u, v, d; cin >> u >> v >> d;
			dist[u][v] = dist[v][u] = d;
		}
		rep(k, n) rep(i, n) rep(j, n) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

		vector<P> vec;
		rep(i, L) {
			int p, t; cin >> p >> t; vec.push_back(P(t, p));
		}
		sort(vec.begin(), vec.end());
		
		mf_graph<int> g(2 * L + 2);
		int s = 2 * L, t = 2 * L + 1;
		rep(i, L) g.add_edge(s, i, 1);
		rep(i, L) g.add_edge(L + i, t, 1);

		rep(i, L) {
			for (j = i + 1; j < L; j++) {
				int dt = get<0>(vec[j]) - get<0>(vec[i]);
				int d = dist[get<1>(vec[j])][get<1>(vec[i])];
				if (d <= dt) {
					g.add_edge(i, L + j, 1);
				}
			}
		}
		
		int ans = L - g.flow(s, t);
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 22788
final_rank: 10

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

vector<int> BipMatch(int n,int m,vector<vector<int>>& g){
    vector<int> L(n,-1),R(m,-1),d(n);
    queue<int> que;
    auto dfs=[&](auto& dfs,int v)->bool{
        int nd=exchange(d[v],0)+1;
        for(auto& u:g[v]){
            if(R[u]==-1 or (d[R[u]]==nd and dfs(dfs,R[u]))){
                L[v]=u,R[u]=v;
                return 1;
            }
        }
        return 0;
    };
    for(;;){
        d.assign(n,0);
        queue<int> dummy;
        swap(que,dummy);
        bool ch=0;   
        rep(i,0,n)if(L[i]==-1){
            que.push(i);
            d[i]=1;
        }
        while(!que.empty()){
            int v=que.front();
            que.pop();
            for(auto& u:g[v]){
                if(R[u]==-1)ch=1;
                else if(!d[R[u]]){
                    d[R[u]]=d[v]+1;
                    que.push(R[u]);
                }
            }
        }
        if(!ch)break;
        rep(i,0,n)if(L[i]==-1)dfs(dfs,i);
    }
    return L;
}

int main() {
while(1) {
    int N, M, L;
    cin >> N >> M >> L;
    if (N == 0) return 0;
    vector<vector<pair<int,int>>> G(N);
    rep(i,0,M) {
        int U, V, D;
        cin >> U >> V >> D;
        G[U].push_back({V,D});
        G[V].push_back({U,D});
    }
    vector<pair<int,int>> P(L);
    rep(i,0,L) {
        cin >> P[i].second >> P[i].first;
    }
    sort(ALL(P));
    auto Dijkstra = [&](int S) -> vector<int> {
        vector<int> DP(N,inf);
        DP[S] = 0;
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
        PQ.push({0,S});
        while(!PQ.empty()) {
            auto [Di, Po] = PQ.top();
            PQ.pop();
            if (DP[Po] < Di) continue;
            for (auto E : G[Po]) {
                int NP = E.first, ND = Di+E.second;
                if (chmin(DP[NP],ND)) {
                    PQ.push({ND,NP});
                }
            }
        }
        return DP;
    };
    vector<vector<int>> Dist(N);
    rep(i,0,N) Dist[i] = Dijkstra(i);
    vector<vector<int>> H(L);
    rep(i,0,L) {
        rep(j,i+1,L) {
            if (P[i].first + Dist[P[i].second][P[j].second] <= P[j].first) H[i].push_back(j);
        }
    }
    auto Ret = BipMatch(L,L,H);
    int ANS = 0;
    rep(i,0,L) if (Ret[i] == -1) ANS++;
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 50
memory_kb: 6048
final_rank: 2

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <cassert>
#include <limits>
#include <queue>
#include <vector>


#include <vector>

namespace atcoder {

namespace internal {

template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

template <class Cap> struct mf_graph {
  public:
    mf_graph() : _n(0) {}
    explicit mf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        int from_id = int(g[from].size());
        int to_id = int(g[to].size());
        if (from == to) to_id++;
        g[from].push_back(_edge{to, to_id, cap});
        g[to].push_back(_edge{from, from_id, 0});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
    };

    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result;
        for (int i = 0; i < m; i++) {
            result.push_back(get_edge(i));
        }
        return result;
    }
    void change_edge(int i, Cap new_cap, Cap new_flow) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        assert(0 <= new_flow && new_flow <= new_cap);
        auto& _e = g[pos[i].first][pos[i].second];
        auto& _re = g[_e.to][_e.rev];
        _e.cap = new_cap - new_flow;
        _re.cap = new_flow;
    }

    Cap flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    Cap flow(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);

        std::vector<int> level(_n), iter(_n);
        internal::simple_queue<int> que;

        auto bfs = [&]() {
            std::fill(level.begin(), level.end(), -1);
            level[s] = 0;
            que.clear();
            que.push(s);
            while (!que.empty()) {
                int v = que.front();
                que.pop();
                for (auto e : g[v]) {
                    if (e.cap == 0 || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    if (e.to == t) return;
                    que.push(e.to);
                }
            }
        };
        auto dfs = [&](auto self, int v, Cap up) {
            if (v == s) return up;
            Cap res = 0;
            int level_v = level[v];
            for (int& i = iter[v]; i < int(g[v].size()); i++) {
                _edge& e = g[v][i];
                if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                Cap d =
                    self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                if (d <= 0) continue;
                g[v][i].cap += d;
                g[e.to][e.rev].cap -= d;
                res += d;
                if (res == up) return res;
            }
            level[v] = _n;
            return res;
        };

        Cap flow = 0;
        while (flow < flow_limit) {
            bfs();
            if (level[t] == -1) break;
            std::fill(iter.begin(), iter.end(), 0);
            Cap f = dfs(dfs, t, flow_limit - flow);
            if (!f) break;
            flow += f;
        }
        return flow;
    }

    std::vector<bool> min_cut(int s) {
        std::vector<bool> visited(_n);
        internal::simple_queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            visited[p] = true;
            for (auto e : g[p]) {
                if (e.cap && !visited[e.to]) {
                    visited[e.to] = true;
                    que.push(e.to);
                }
            }
        }
        return visited;
    }

  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};

}  // namespace atcoder

using namespace std;

bool solve() {
    int N, M, L;
    cin >> N >> M >> L;
    if (N == 0 && M == 0 && L == 0) return false;
    vector<vector<int>> dist(N, vector<int>(N, 1 << 29));
    for (int i = 0; i < N; i++) {
        dist[i][i] = 0;
    }
    for (int i = 0; i < M; i++) {
        int u, v, d;
        cin >> u >> v >> d;
        dist[u][v] = dist[v][u] = d;
    }
    for (int k = 0; k < N; k++) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    vector<int> p(L), t(L);
    for (int i = 0; i < L; i++) cin >> p[i] >> t[i];
    atcoder::mf_graph<int> G(2 * L + 2);
    int S = 2 * L, T = 2 * L + 1;
    for (int i = 0; i < L; i++) {
        G.add_edge(S, i, 1);
        G.add_edge(i + L, T, 1);
        for (int j = 0; j < L; j++) {
            if (i != j && t[i] <= t[j] && t[j] - t[i] >= dist[p[i]][p[j]]) {
                G.add_edge(i, j + L, 1);
            }
        }
    }
    cout << L - G.flow(S, T) << endl;
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while (solve()) {}
}
accuracy: 1
time_ms: 360
memory_kb: 23000
final_rank: 13

code_snippet: #include<bits/stdc++.h>

#include <algorithm>

#include <vector>

namespace atcoder {

namespace internal {

template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <limits>
#include <queue>
#include <vector>

namespace atcoder {

template <class Cap> struct mf_graph {
  public:
    mf_graph() : _n(0) {}
    mf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        int from_id = int(g[from].size());
        int to_id = int(g[to].size());
        if (from == to) to_id++;
        g[from].push_back(_edge{to, to_id, cap});
        g[to].push_back(_edge{from, from_id, 0});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
    };

    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result;
        for (int i = 0; i < m; i++) {
            result.push_back(get_edge(i));
        }
        return result;
    }
    void change_edge(int i, Cap new_cap, Cap new_flow) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        assert(0 <= new_flow && new_flow <= new_cap);
        auto& _e = g[pos[i].first][pos[i].second];
        auto& _re = g[_e.to][_e.rev];
        _e.cap = new_cap - new_flow;
        _re.cap = new_flow;
    }

    Cap flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    Cap flow(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);

        std::vector<int> level(_n), iter(_n);
        internal::simple_queue<int> que;

        auto bfs = [&]() {
            std::fill(level.begin(), level.end(), -1);
            level[s] = 0;
            que.clear();
            que.push(s);
            while (!que.empty()) {
                int v = que.front();
                que.pop();
                for (auto e : g[v]) {
                    if (e.cap == 0 || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    if (e.to == t) return;
                    que.push(e.to);
                }
            }
        };
        auto dfs = [&](auto self, int v, Cap up) {
            if (v == s) return up;
            Cap res = 0;
            int level_v = level[v];
            for (int& i = iter[v]; i < int(g[v].size()); i++) {
                _edge& e = g[v][i];
                if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                Cap d =
                    self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                if (d <= 0) continue;
                g[v][i].cap += d;
                g[e.to][e.rev].cap -= d;
                res += d;
                if (res == up) break;
            }
            return res;
        };

        Cap flow = 0;
        while (flow < flow_limit) {
            bfs();
            if (level[t] == -1) break;
            std::fill(iter.begin(), iter.end(), 0);
            while (flow < flow_limit) {
                Cap f = dfs(dfs, t, flow_limit - flow);
                if (!f) break;
                flow += f;
            }
        }
        return flow;
    }

    std::vector<bool> min_cut(int s) {
        std::vector<bool> visited(_n);
        internal::simple_queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            visited[p] = true;
            for (auto e : g[p]) {
                if (e.cap && !visited[e.to]) {
                    visited[e.to] = true;
                    que.push(e.to);
                }
            }
        }
        return visited;
    }

  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};

}  // namespace atcoder

using namespace atcoder;
using namespace std;
using ll=long long;
using vll=vector<ll>;
using vvll=vector<vll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)


void warshall_floyd(vvll &d) {
	int n=d.size();
	for (int k = 0; k < n; k++) {       // 経由する頂点
		for (int i = 0; i < n; i++) {    // 始点
			for (int j = 0; j < n; j++) {  // 終点
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
}

void solve(ll N,ll M,ll L){
    vvll D(N,vll(N,1e18));
    rep(i,N)D[i][i]=0;
    rep(i,M){
        ll u,v,d;
        cin>>u>>v>>d;
        D[u][v]=d;
        D[v][u]=d;
    }
    warshall_floyd(D);
    mf_graph<ll> G(L*2+2);
    ll S=L*2;
    ll T=L*2+1;
    rep(i,L){
        G.add_edge(S,i,1);
        G.add_edge(i+L,T,1);
    }
    vll P(L),Q(L);
    rep(i,L){
        cin>>P[i]>>Q[i];
        rep(j,i){
            if(D[P[i]][P[j]]<=abs(Q[i]-Q[j])){
                if(Q[i]<Q[j]){
                    G.add_edge(i,j+L,1);
                }
                else{
                    G.add_edge(j,i+L,1);
                }
            }
        }
    }
    cout<<L-G.flow(S,T)<<endl;
}

int main(){
    ll N,M,L;
    while(cin>>N>>M>>L,N+M+L!=0)solve(N,M,L);
}
accuracy: 1
time_ms: 390
memory_kb: 27220
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
using vll=vector<ll>;
using vvll=vector<vll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)


template <class flow_t = long long>
struct FordFulkerson {
  // edge[e.rev][e.to] で逆辺参照
  struct edge {
    int to;
    int rev;
    flow_t cap;
  };

  int siz;
  vector<vector<edge>> graph;
  vector<bool> used;

  FordFulkerson(int n) : siz(n), graph(n), used(siz, false) {}

  void add_edge(int from, int to, flow_t cap) {
    assert(from < siz && to < siz);
    graph[from].emplace_back((edge){to, (int)graph[to].size(), cap});
    graph[to].emplace_back((edge){from, (int)graph[from].size() - 1, 0});  // -1 大事！
  }

  flow_t dfs(int v, int target, flow_t flow) {
    if (v == target) {
      return flow;
    }
    used[v] = true;

    for (auto &e : graph[v]) {
      if (e.cap > 0 && !used[e.to]) {
        flow_t f = dfs(e.to, target, min(flow, e.cap));
        if (f > 0) {
          e.cap -= f;
          graph[e.to][e.rev].cap += f;
          return f;
        }
      }
    }
    return 0;
  }

  // max flow on s -> t
  flow_t max_flow(int s, int t) {
    flow_t flow = 0;
    flow_t INF = 1e9;  // INF の上限値に注意
    while (true) {
      used.assign(siz, false);
      flow_t f = dfs(s, t, INF);
      flow += f;

      if (f == 0) {
        return flow;
      }
    }
    // 絶対に到達しないはず
    return 0;
  }
};

void warshall_floyd(vvll &d) {
	int n=d.size();
	for (int k = 0; k < n; k++) {       // 経由する頂点
		for (int i = 0; i < n; i++) {    // 始点
			for (int j = 0; j < n; j++) {  // 終点
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
}

void solve(ll N,ll M,ll L){
    vvll D(N,vll(N,1e18));
    rep(i,N)D[i][i]=0;
    rep(i,M){
        ll u,v,d;
        cin>>u>>v>>d;
        D[u][v]=d;
        D[v][u]=d;
    }
    warshall_floyd(D);
    FordFulkerson G(L*2+2);
    ll S=L*2;
    ll T=L*2+1;
    rep(i,L){
        G.add_edge(S,i,1);
        G.add_edge(i+L,T,1);
    }
    vll P(L),Q(L);
    rep(i,L){
        cin>>P[i]>>Q[i];
        rep(j,i){
            if(D[P[i]][P[j]]<=abs(Q[i]-Q[j])){
                if(Q[i]<Q[j]){
                    G.add_edge(i,j+L,1);
                }
                else{
                    G.add_edge(j,i+L,1);
                }
            }
        }
    }
    cout<<L-G.max_flow(S,T)<<endl;
}

int main(){
    ll N,M,L;
    while(cin>>N>>M>>L,N+M+L!=0)solve(N,M,L);
}
accuracy: 1
time_ms: 1520
memory_kb: 23200
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;


struct Dinic {
private:
    const long long inf = 1e18;
    vector<int> dist; //sからの距離
    vector<int> iter; //どこまで調べたか
public:
    struct edge {
        int to, rev; long long cap;
        edge(int t = 0, int r = 0, long long c = 0LL) : to(t), rev(r), cap(c) {}
    };

    int n;
    vector<vector<edge>> to;

    Dinic(int n_ = 1) : n(n_), to(n_), dist(n_), iter(n_) {}

    void addedge(int u, int v, long long cap) {//u->vにcapの容量
        int su = (int)to[u].size(), sv = (int)to[v].size();
        to[u].push_back({ v, sv, cap });
        to[v].push_back({ u, su, 0 });
    }

    long long dfs(int v, int t, long long f) { //t: 終点, f: flow
        if (v == t) return f;
        int sv = (int)to[v].size();
        for (int& i = iter[v]; i < sv; i++) {
            edge& nv = to[v][i];
            if (dist[nv.to] <= dist[v] || nv.cap == 0) continue; //here
            long long nf = dfs(nv.to, t, min(f, nv.cap));
            if (nf > 0) {
                nv.cap -= nf;
                to[nv.to][nv.rev].cap += nf;
                return nf;
            }
        }
        return 0;
    }

    void bfs(int s) {
        dist.assign(n, -1);
        queue<int> q;
        q.push(s);
        dist[s] = 0;
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (auto nv : to[v]) {
                if (nv.cap > 0 && dist[nv.to] < 0) {
                    dist[nv.to] = dist[v] + 1;
                    q.push(nv.to);
                }
            }
        }
    }

    long long maxflow(int s, int t) {//s:始点, t:終点
        long long res = 0, flow = 0;
        while (true) {
            bfs(s);
            if (dist[t] < 0) break;

            iter.assign(n, 0);
            while (flow = dfs(s, t, inf)) res += flow;
        };
        return res;
    }
};

struct edge {
    int to, cost;
};

int main()
{
    vi<int> ans;
    const int inf = 1e9;
    int n, m, l;
    while (cin >> n >> m >> l, n) {
        vii<int> dist(n, vi<int>(n, inf));
        rep(i, n) dist[i][i] = 0;
        rep(i, m) {
            int u, v, d;
            cin >> u >> v >> d;
            dist[u][v] = d;
            dist[v][u] = d;
        }

        rep(k, n) rep(i, n) rep(j, n) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

        vi<int> p(l), t(l);
        rep(i, l) cin >> p[i] >> t[i];

        Dinic dn(2 * l + 2);
        int S = 2 * l, T = S + 1;

        rep(i, l) dn.addedge(S, i, 1);
        rep(j, l) dn.addedge(j + l, T, 1);

        rep(i, l) {
            rep(j, l) {
                if (i == j) continue;
                if (dist[p[i]][p[j]] == inf) continue;
                if (t[i] + dist[p[i]][p[j]] > t[j]) continue;
                dn.addedge(i, j + l, 1);
            }
        }

        int flow = dn.maxflow(S, T);
        ans.push_back(l - flow);
    }

    for (int elem : ans) cout << elem << endl;
    return 0;
}
accuracy: 1
time_ms: 520
memory_kb: 23916
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define endl "\n"
#define bug(x) cerr << #x << " = " << x << endl
#define sz(x) (int)x.size()
#define mp make_pair
#define LL long long

#define INF 1000000007
#define MX 2005
#define NX 205
#define NN 3005

int n, m, Q;
pair<int, int> q[MX];
int dis[NX][NX];

int an, bn;
int ud[NN];
int ab[NN], ba[NN];
int vis[NN], T;
vector<int> adj[NN];

void BFS(){
	queue<int> q; while(!q.empty()) q.pop();
	
	fill_n(ud, an, -1);
	for(int u = 0; u < an; u ++) if(ab[u] == -1){
		q.push(u); ud[u] = 0;
	}
	
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int v : adj[u]) if(ab[u] != v){
			int nu = ba[v];
			if(~nu && ud[nu] == -1){
				q.push(nu); ud[nu] = ud[u] + 1;
			}
		}
	}
}

int DFS(int u){
	vis[u] = T;
	for(int v : adj[u]) if(ab[u] != v){
		int i = ba[v];
		if((i == -1) || (vis[i] != T && ud[i] == ud[u] + 1 && DFS(i))){
			ba[v] = u; ab[u] = v;
			return 1;
		}
	}
	return 0;
}

int Hopcroft_Karp(){
	
	fill_n(ab, an, -1);
	fill_n(ba, bn, -1);
	fill_n(vis, an, 0);
	
	int rlt = 0;
	T = 0;
	while(1){
		T ++;
		BFS();
		int f = 0;
		for(int u = 0; u < an; u ++) if(ab[u] == -1 && DFS(u)) f ++;
		if(!f) break;
		rlt += f;
	}
	
	return rlt;
}

void solve(){

	while( cin >> n >> m >> Q && (n || m || Q)){
		
		fill_n(dis[0], NX * NX, INF);
		for(int i = 0; i < n; i ++) dis[i][i] = 0;
		
		for(int i = 0; i < m; i ++){
			int u, v, d; cin >> u >> v >> d;
			dis[u][v] = min(dis[u][v], d);
			dis[v][u] = min(dis[v][u], d);
		}
		for(int i = 0; i < Q; i ++) cin >> q[i].first >> q[i].second;
		
		for(int k = 0; k < n; k ++){
			for(int i = 0; i < n; i ++) for(int j = 0; j < n; j ++){
				dis[i][j] = min(dis[i][k] + dis[k][j], dis[i][j]);
			}
		}
		
		for(int i = 0; i < Q; i ++) adj[i].clear();
		for(int i = 0; i < Q; i ++) for(int j = 0; j < Q; j ++) if(i != j){
			if(dis[q[i].first][q[j].first] <= q[j].second - q[i].second) adj[i].push_back(j);
		}
		an = bn = Q;
		
		int M = Hopcroft_Karp();
		
		cout << Q - M << endl;
	}
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
//	freopen("in.txt", "r", stdin);

	int Tc = 1;
//	cin >> Tc;
	while(Tc --){
		solve();
	}

	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 7884
final_rank: 5

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

#define sz(x) (int((x).size()))
int n;
typedef vector<int> VI;
const int MX = 2005;
int an, bn;
VI adj[MX];
int ab[MX], ba[MX];
int dis[MX];
int q[MX], hd, tl;
int vis[MX], T;

void BFS() {
	int i, u, v, uu;
	hd = tl = 0;
	for (u = 0; u < an; u++) {
		if (ab[u] == -1) {
			dis[u] = 0;
			q[tl++] = u;
		}
		else dis[u] = -1;
	}
	while (hd < tl) {
		u = q[hd++];
		for (i = sz(adj[u]) - 1; i >= 0; i--) {
			v = adj[u][i];
			uu = ba[v];
			if (~uu && dis[uu] == -1) {
				dis[uu] = dis[u] + 1;
				q[tl++] = uu;
			}
		}
	}
}

bool DFS(int u) {
	int i, v, uu;
	vis[u] = T;
	for (i = sz(adj[u]) - 1; i >= 0; i--) {
		v = adj[u][i];
		uu = ba[v];
		if (uu == -1 || vis[uu] != T && dis[uu] == dis[u] + 1 && DFS(uu)) {
			ab[u] = v, ba[v] = u;
			return 1;
		}
	}
	return 0;
}

int Hopcroft_Karp() {
	int u, k, m;
	fill_n(ab, an, -1);
	fill_n(ba, bn, -1);
	m = 0;
	while (1) {
		BFS();
		T++;
		k = 0;
		for (u = 0; u < an; u++) {
			if (ab[u] == -1 && DFS(u)) k++;
		}
		if (!k) break;
		m += k;
	}
	return m;
}

int N, M, L;
int d[1005][1005];
const int inf = 1e9 + 7;
int p[MX], t[MX];
void solve() {
	while(cin >> N >> M >> L && (N + M + L)){
		int n = N;
		for(int i = 0 ; i< N ; i ++) for(int j = 0 ; j < N; j++) d[i][j] = inf;
		for(int i = 0 ; i < M; i ++){
			int u, v, w;
			cin >> u >> v>> w;
			d[u][v] = min(d[u][v], w);
			d[v][u] = min(d[v][u], w);
		}
		for(int i = 0 ; i < n ; i ++) d[i][i] = 0;
		for(int k = 0 ; k < n ; k ++) for(int i = 0 ; i < n ; i ++) for(int j = 0;j < n ; j ++) d[i][j] = min(d[i][k] + d[k][j] , d[i][j]);
		
//		for(int i = 0 ; i < n ; i ++) {
//			for(int j = 0; j < n ; j ++) cout << d[i][j] <<" ";
//			cout << endl;
//		}
		for(int i = 0 ; i < L; i ++ ){
			cin >> p[i] >> t[i];
		}
		
		for(int i = 0 ; i < L; i ++) adj[i].clear();
		
		an = bn =L;
		for(int i = 0 ; i < L; i ++){
			for(int j  = 0 ; j < L; j ++){
				if(i == j) continue;
				if(t[i] + d[p[i]][p[j]] <= t[j]) adj[i].push_back(j);
			}
		}
		cout << L - Hopcroft_Karp() << endl;
	}
}

int main() {
//#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//#endif
//    ios::sync_with_stdio(0);
//    cin.tie(0), cout.tie(0);

	int Tc = 1;

	while (Tc--) solve();

    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 8040
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;
int n;
const int inf = 1e9 + 7;
const int MN = 2e3 + 5;
#define sz(x) (int((x).size()))

typedef vector<int> VI;
const int MX = 2005;

int an, bn;
vector<int> adj[MX];
int ab[MX], ba[MX];
int dis[MX];
int q[MX], hd, tl;
int vis[MX], T;

void BFS() {
	int i, u, v, uu;
	hd = tl = 0;
	for (u = 0; u < an; u++) {
		if (ab[u] == -1) {
			dis[u] = 0;
			q[tl++] = u;
		}
		else dis[u] = -1;
	}
	while (hd < tl) {
		u = q[hd++];
		for (i = sz(adj[u]) - 1; i >= 0; i--) {
			v = adj[u][i];
			uu = ba[v];
			if (~uu && dis[uu] == -1) {
				dis[uu] = dis[u] + 1;
				q[tl++] = uu;
			}
		}
	}
}

bool DFS(int u) {
	int i, v, uu;
	vis[u] = T;
	for (i = sz(adj[u]) - 1; i >= 0; i--) {
		v = adj[u][i];
		uu = ba[v];
		if (uu == -1 || vis[uu] != T && dis[uu] == dis[u] + 1 && DFS(uu)) {
			ab[u] = v, ba[v] = u;
			return 1;
		}
	}
	return 0;
}

int Hopcroft_Karp() {
	int u, k, m;
	fill_n(ab, an, -1);
	fill_n(ba, bn, -1);
//	fill_n(vis, an, 0);
	m = 0;
	while (1) {
		BFS();
		T++;
		k = 0;
		for (u = 0; u < an; u++) {
			if (ab[u] == -1 && DFS(u)) k++;
		}
		if (!k) break;
		m += k;
	}
	return m;
}


template<class T>
inline void chkmin(T& x, T y) {
	if (y < x) x = y;
}

int w[MN][MN], d[MN][MN];

void Floyd_Warshall() {
	int i, j, k;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) d[i][j] = w[i][j];
	}
	for(int i = 0 ; i < n; i ++) d[i][i] = 0;
	for (k = 0; k < n; k++) {
		for (i = 0; i < n; i++) {
			for (j = 0; j < n; j++)
				chkmin(d[i][j], d[i][k] + d[k][j]);
		}
	}
}

int p[MX], t[MX];
void solve() {
	int N, M, L;
	while(cin >> N >> M >> L && (N + M + L)){
		n = N;
 		for(int i = 0; i < n ; i ++){
			for(int j = 0; j < n ; j++){
				w[i][j] = inf;
				d[i][j] = inf;
			}
		}
		for(int i = 0 ; i < M ; i ++){
			int u, v, ww;
			cin >> u >> v >> ww;
			chkmin(w[u][v], ww);
			chkmin(w[v][u], ww);
		}
		Floyd_Warshall();
		for(int i = 0 ; i < L; i ++){
			cin >> p[i] >> t[i];
		}
		for(int i = 0 ; i < L; i ++){
			adj[i].clear();
		}
		an = bn = L;
		for(int i = 0 ; i < L; i ++){
			for(int j = 0; j < L; j ++){
				if(i == j){
					continue;
				}
				if(t[i] + d[p[i]][p[j]] <= t[j]){
					adj[i].push_back(j);
				}
			}
		}
		cout << L - Hopcroft_Karp() << endl;
	}
}

int main() {
#ifndef ONLINE_JUDGE
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	int Tc = 1;
//	cin >> Tc;
	while (Tc --) {
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 12252
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int INF = (1<<29);
int n, m, l, match[2001];
vector<vector<int> > g;
bool used[1001];
bool dfs(int v){
    used[v] = true;
    for(int i=0;i<g[v].size();i++){
        int u = g[v][i];
        int w = match[u];
        if(w<0 || !used[w]&&dfs(w)){
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}
int bm(){
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int i=0;i<l;i++){
        if(match[i]<0){
            memset(used, false, sizeof(used));
            if(dfs(i)) res++;
        }
    }
    return res;
}
int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    int u, v, d, mcost[101][101];
    while(cin >> n >> m >> l, n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++) mcost[i][j] = INF;
            mcost[i][i] = 0;
        }
        for(int i=0;i<m;i++){
            cin >> u >> v >> d;
            mcost[u][v] = d;
            mcost[v][u] = d;
        }
        for(int k=0;k<n;k++){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++) mcost[i][j] = min(mcost[i][j], mcost[i][k]+mcost[k][j]);
            }
        }
        int p[1001], t[1001];
        vector<vector<int> > path(1001);
        for(int i=0;i<l;i++){
            cin >> p[i] >> t[i];
            for(int j=0;j<i;j++){
                int dis = mcost[p[j]][p[i]];
                if(t[j]+dis<=t[i]) path[j].push_back(i+l);
                if(t[i]+dis<=t[j]) path[i].push_back(j+l);
            }
        }
        g = path;
        cout << l-bm() << endl;
    }
    return(0);
}
accuracy: 1
time_ms: 680
memory_kb: 8356
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int INF = (1<<29);
int n, m, l, match[2001];
vector<vector<int> > g;
bool used[1001];
bool dfs(int v){
    used[v] = true;
    for(int i=0;i<g[v].size();i++){
        int u = g[v][i];
        int w = match[u];
        if(w<0 || !used[w]&&dfs(w)){
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}
int bm(){
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int i=0;i<l;i++){
        if(match[i]<0){
            memset(used, false, sizeof(used));
            if(dfs(i)) res++;
        }
    }
    return res;
}
int main(){
    int u, v, d, mcost[101][101];
    while(cin >> n >> m >> l, n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++) mcost[i][j] = INF;
            mcost[i][i] = 0;
        }
        for(int i=0;i<m;i++){
            cin >> u >> v >> d;
            mcost[u][v] = d;
            mcost[v][u] = d;
        }
        for(int k=0;k<n;k++){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++) mcost[i][j] = min(mcost[i][j], mcost[i][k]+mcost[k][j]);
            }
        }
        int p[1001], t[1001];
        vector<vector<int> > path(1001);
        for(int i=0;i<l;i++){
            cin >> p[i] >> t[i];
            for(int j=0;j<i;j++){
                int dis = mcost[p[j]][p[i]];
                if(t[j]+dis<=t[i]) path[j].push_back(i+l);
                if(t[i]+dis<=t[j]) path[i].push_back(j+l);
            }
        }
        g = path;
        cout << l-bm() << endl;
    }
    return(0);
}
accuracy: 1
time_ms: 690
memory_kb: 8316
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using ld = long double;

mt19937 engine(42);

template<class T>
bool chmax(T &a, const T &b) {if (a < b) {a = b; return 1;} return 0;}

template<class T>
bool chmin(T &a, const T &b) {if (a > b) {a = b; return 1;} return 0;}

bool is_end = false;
const ll INF = 1e18;

void warshall_floyd(vector<vector<ll>> &dist)
{
    int n = dist.size();
    for (int i = 0; i < n; ++i) {dist[i][i] = 0;}
    
    for (int k = 0; k < n; ++k)
    {
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                chmin(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    
    return;
}

template<class flow_t = long long>
struct FordFulkerson
{
    struct edge
    {
        int to;
        int rev;
        flow_t cap;
    };
    
    int siz;
    vector<vector<edge>> graph;
    vector<bool> used;
    
    FordFulkerson(int n) : siz(n), graph(n), used(siz, false) { }
    
    void add_edge(int from, int to, flow_t cap)
    {
        assert(from < siz && to < siz);
        graph[from].emplace_back((edge){to, (int)graph[to].size(), cap});
        graph[to].emplace_back((edge){from, (int)graph[from].size() - 1, 0});
    }
    
    flow_t dfs(int v, int target, flow_t flow)
    {
        if (v == target) return flow;
        used[v] = true;
        
        for (auto &e : graph[v])
        {
            if (e.cap > 0 && !used[e.to])
            {
                flow_t f = dfs(e.to, target, min(flow, e.cap));
                if (f > 0)
                {
                    e.cap -= f;
                    graph[e.to][e.rev].cap += f;
                    return f;
                }
            }
        }
        return 0;
    }
    
    flow_t max_flow(int s, int t)
    {
        flow_t flow = 0;
        flow_t INF = 1e9;
        while (true)
        {
            used.assign(siz, false);
            flow_t f = dfs(s, t, INF);
            flow += f;
            
            if (f == 0) return flow;
        }
        return 0;
    }
    
};

void calc()
{
    ll N, M, L; cin >> N >> M >> L;
    if (N == 0)
    {
        is_end = true;
        return;
    }
    
    vector<vector<ll>> dist(N, vector<ll>(N, INF));
    for (int i = 0; i < M; ++i)
    {
        ll u, v, d; cin >> u >> v >> d;
        dist[u][v] = dist[v][u] = d;
    }
    
    warshall_floyd(dist);
    
    vector<pair<ll, ll>> request(L);
    for (int i = 0; i < L; ++i)
    {
        ll p, t; cin >> p >> t;
        request[i] = {t, p};
    }
    sort(request.begin(), request.end());
    
    ll S = 2*L, T = S+1;
    FordFulkerson<ll> graph(T+1);
    for (int i = 0; i < L; ++i)
    {
        auto [ti, pi] = request[i];
        graph.add_edge(S, i, 1);
        graph.add_edge(i+L, T, 1);
        
        for (int j = i+1; j < L; ++j)
        {
            auto [tj, pj] = request[j];
            if (ti + dist[pi][pj] <= tj)
            {
                graph.add_edge(i, j+L, 1);
            }
        }
    }
    
    ll f = graph.max_flow(S, T);
    cout << L - f << endl;
    
    
    return;
}

int main() {
    
    while (!is_end)
    {
        calc();
    }
    
    return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 24440
final_rank: 17

code_snippet: #line 1 "a.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/GRL_7_A"
#line 2 "/home/kuhaku/home/github/algo/lib/template/template.hpp"
#pragma GCC target("sse4.2,avx2,bmi2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
template <class T, class U>
bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr int MOD = 1000000007;
constexpr int MOD_N = 998244353;
constexpr double EPS = 1e-7;
constexpr double PI = M_PI;
#line 2 "/home/kuhaku/home/github/algo/lib/flow/hopcroft_karp.hpp"

struct hopcroft_karp {
    hopcroft_karp(int _n, int _m) : n(_n), m(_m), g(_n), match_left(_n, -1), match_right(_m, -1) {}

    void add_edge(int u, int v) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < m);
        g[u].emplace_back(v);
    }

    int matching() {
        int flow = 0;
        std::vector<int> root(n), prev(n), qq(n);
        for (bool updated = true; updated;) {
            updated = false;
            int qi = 0, qj = 0;
            std::fill(root.begin(), root.end(), -1);
            std::fill(prev.begin(), prev.end(), -1);
            for (int i = 0; i < n; i++) {
                if (match_left[i] == -1) qq[qj++] = i, root[i] = i, prev[i] = i;
            }
            while (qi < qj) {
                int u = qq[qi++];
                if (match_left[root[u]] != -1) continue;
                for (int v : g[u]) {
                    if (match_right[v] == -1) {
                        while (v != -1)
                            match_right[v] = u, std::swap(match_left[u], v), u = prev[u];
                        updated = true, flow++;
                        break;
                    }

                    if (prev[match_right[v]] == -1)
                        v = match_right[v], prev[v] = u, root[v] = root[u], qq[qj++] = v;
                }
            }
        }
        return flow;
    }

    std::vector<std::pair<int, int>> get_pairs() const {
        std::vector<std::pair<int, int>> res;
        for (int i = 0; i < n; i++) {
            if (~match_left[i]) res.emplace_back(i, match_left[i]);
        }
        return res;
    }

  private:
    const int n, m;
    std::vector<std::vector<int>> g;
    std::vector<int> match_left, match_right;
};
#line 3 "/home/kuhaku/home/github/algo/lib/graph/matrix_graph.hpp"

/**
 * @brief 隣接行列
 *
 * @tparam T
 */
template <class T>
struct matrix_graph {
    matrix_graph(int v, T e = T()) : _size(v), m(v, std::vector<T>(v, e)) {}

    const auto &operator[](int i) const { return this->m[i]; }
    auto &operator[](int i) { return this->m[i]; }
    const auto begin() const { return this->m.begin(); }
    auto begin() { return this->m.begin(); }
    const auto end() const { return this->m.end(); }
    auto end() { return this->m.end(); }

    constexpr int size() const { return this->_size; }

    void add_edge(int a, int b, T d = T(1)) { this->m[a][b] = d; }
    void add_edges(int a, int b, T d = T(1)) { this->m[a][b] = this->m[b][a] = d; }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            this->add_edge(from - base, to - base, weight);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            this->add_edges(from - base, to - base, weight);
        }
    }

  private:
    int _size;
    std::vector<std::vector<T>> m;
};

template <>
struct matrix_graph<void> {
    matrix_graph(int v) : _size(v), m(v, std::vector<bool>(v)) {}

    const auto &operator[](int i) const { return this->m[i]; }
    auto &operator[](int i) { return this->m[i]; }
    const auto begin() const { return this->m.begin(); }
    auto begin() { return this->m.begin(); }
    const auto end() const { return this->m.end(); }
    auto end() { return this->m.end(); }

    constexpr int size() const { return this->_size; }

    void add_edge(int a, int b) { this->m[a][b] = true; }
    void add_edges(int a, int b) { this->m[a][b] = this->m[b][a] = true; }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            this->add_edge(from - base, to - base);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            this->add_edges(from - base, to - base);
        }
    }

    void complement() {
        for (int i = 0; i < this->_size; ++i) {
            for (int j = 0; j < this->_size; ++j) this->m[i][j] = !this->m[i][j];
        }
    }

  private:
    int _size;
    std::vector<std::vector<bool>> m;
};
#line 4 "/home/kuhaku/home/github/algo/lib/graph/warshall_floyd.hpp"

template <class T>
void warshall_floyd(matrix_graph<T> &g) {
    int n = g.size();
    for (int i = 0; i < n; ++i) g[i][i] = T();
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                chmin(g[i][j], g[i][k] + g[k][j]);
            }
        }
    }
}
#line 3 "/home/kuhaku/home/github/algo/lib/template/macro.hpp"
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
#line 3 "/home/kuhaku/home/github/algo/lib/template/sonic.hpp"
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
    }

    constexpr void operator()() const {}
} sonic;
#line 5 "/home/kuhaku/home/github/algo/lib/template/atcoder.hpp"
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) {
        os << (it == v.begin() ? "" : " ") << *it;
    }
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0) return std::vector<T>(arg, x);
    else return std::vector(arg, make_vector<T>(x, args...));
}
void setp(int n) {
    std::cout << std::fixed << std::setprecision(n);
}
void Yes(bool is_correct = true) {
    std::cout << (is_correct ? "Yes" : "No") << '\n';
}
void No(bool is_not_correct = true) {
    Yes(!is_not_correct);
}
void YES(bool is_correct = true) {
    std::cout << (is_correct ? "YES" : "NO") << '\n';
}
void NO(bool is_not_correct = true) {
    YES(!is_not_correct);
}
void Takahashi(bool is_correct = true) {
    std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n';
}
void Aoki(bool is_not_correct = true) {
    Takahashi(!is_not_correct);
}
#line 6 "a.cpp"

int main(void) {
    while (true) {
        int n, m, l;
        cin >> n >> m >> l;
        if (!n)
            break;
        matrix_graph<int> g(n, Inf);
        while (m--) {
            int u, v, w;
            cin >> u >> v >> w;
            g.add_edges(u, v, w);
        }
        warshall_floyd(g);
        vector<pair<int, int>> q(l);
        cin >> q;
        sort(all(q), [](auto l, auto r) {
            return l.second < r.second;
        });
        hopcroft_karp hk(l, l);
        rep (i, l) {
            auto [a, b] = q[i];
            FOR (j, i + 1, l) {
                auto [c, d] = q[j];
                if (b + g[a][c] <= d)
                    hk.add_edge(i, j);
            }
        }
        co(l - hk.matching());
    }

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 6148
final_rank: 1

code_snippet: #line 1 "main.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2251"
#line 1 "library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'000'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;

using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define FOR_subset(t, s) \
  for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_mod_2(int x) { return __builtin_parity(x); }
int popcnt_mod_2(u32 x) { return __builtin_parity(x); }
int popcnt_mod_2(ll x) { return __builtin_parityll(x); }
int popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T, typename U>
T ceil(T x, U y) {
  return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U>
T floor(T x, U y) {
  return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template <typename T, typename U>
T SUM(const vector<U> &A) {
  T sum = 0;
  for (auto &&a: A) sum += a;
  return sum;
}

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  assert(!que.empty());
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  assert(!que.empty());
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
  FOR(iter) {
    double x = (ok + ng) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return (ok + ng) / 2;
}

template <class T, class S>
inline bool chmax(T &a, const S &b) {
  return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
  return (a > b ? a = b, 1 : 0);
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
  int N = A.size();
  vector<T> B(N + 1);
  FOR(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vector<int> argsort(const vector<T> &A) {
  vector<int> ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  vc<T> B(len(I));
  FOR(i, len(I)) B[i] = A[I[i]];
  return B;
}
#endif
#line 1 "library/other/io.hpp"
// based on yosupo's fastio
#include <unistd.h>

namespace fastio {
#define FASTIO
// クラスが read(), print() を持っているかを判定するメタ関数
struct has_write_impl {
  template <class T>
  static auto check(T &&x) -> decltype(x.write(), std::true_type{});

  template <class T>
  static auto check(...) -> std::false_type;
};

template <class T>
class has_write : public decltype(has_write_impl::check<T>(std::declval<T>())) {
};

struct has_read_impl {
  template <class T>
  static auto check(T &&x) -> decltype(x.read(), std::true_type{});

  template <class T>
  static auto check(...) -> std::false_type;
};

template <class T>
class has_read : public decltype(has_read_impl::check<T>(std::declval<T>())) {};

struct Scanner {
  FILE *fp;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed) return false;
      }
      while (st != ed && isspace(line[st])) st++;
      if (st != ed) break;
    }
    if (ed - st <= 50) {
      bool sep = false;
      for (size_t i = st; i < ed; i++) {
        if (isspace(line[i])) {
          sep = true;
          break;
        }
      }
      if (!sep) reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz])) sz++;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed) break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) { ref = 10 * ref + (line[st++] & 0xf); }
    if (neg) ref = -ref;
    return true;
  }
  template <typename T,
            typename enable_if<has_read<T>::value>::type * = nullptr>
  inline bool read_single(T &x) {
    x.read();
    return true;
  }
  bool read_single(double &ref) {
    string s;
    if (!read_single(s)) return false;
    ref = std::stod(s);
    return true;
  }
  bool read_single(char &ref) {
    string s;
    if (!read_single(s) || s.size() != 1) return false;
    ref = s[0];
    return true;
  }
  template <class T>
  bool read_single(vector<T> &ref) {
    for (auto &d: ref) {
      if (!read_single(d)) return false;
    }
    return true;
  }
  template <class T, class U>
  bool read_single(pair<T, U> &p) {
    return (read_single(p.first) && read_single(p.second));
  }
  template <size_t N = 0, typename T>
  void read_single_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
      auto &x = std::get<N>(t);
      read_single(x);
      read_single_tuple<N + 1>(t);
    }
  }
  template <class... T>
  bool read_single(tuple<T...> &tpl) {
    read_single_tuple(tpl);
    return true;
  }
  void read() {}
  template <class H, class... T>
  void read(H &h, T &... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE *fp) : fp(fp) {}
};

struct Printer {
  Printer(FILE *_fp) : fp(_fp) {}
  ~Printer() { flush(); }

  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write(const char val) {
    if (pos == SIZE) flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write(T val) {
    if (pos > (1 << 15) - 50) flush();
    if (val == 0) {
      write('0');
      return;
    }
    if (val < 0) {
      write('-');
      val = -val; // todo min
    }
    size_t len = 0;
    while (val) {
      small[len++] = char(0x30 | (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; i++) { line[pos + i] = small[len - 1 - i]; }
    pos += len;
  }
  void write(const string s) {
    for (char c: s) write(c);
  }
  void write(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++) write(s[i]);
  }
  void write(const double x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  void write(const long double x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  template <typename T,
            typename enable_if<has_write<T>::value>::type * = nullptr>
  inline void write(T x) {
    x.write();
  }
  template <class T>
  void write(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  template <class T, class U>
  void write(const pair<T, U> val) {
    write(val.first);
    write(' ');
    write(val.second);
  }
  template <size_t N = 0, typename T>
  void write_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
      if constexpr (N > 0) { write(' '); }
      const auto x = std::get<N>(t);
      write(x);
      write_tuple<N + 1>(t);
    }
  }
  template <class... T>
  bool write(tuple<T...> tpl) {
    write_tuple(tpl);
    return true;
  }
  template <class T, size_t S>
  void write(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  void write(i128 val) {
    string s;
    bool negative = 0;
    if (val < 0) {
      negative = 1;
      val = -val;
    }
    while (val) {
      s += '0' + int(val % 10);
      val /= 10;
    }
    if (negative) s += "-";
    reverse(all(s));
    if (len(s) == 0) s = "0";
    write(s);
  }
};
Scanner scanner = Scanner(stdin);
Printer printer = Printer(stdout);
void flush() { printer.flush(); }
void print() { printer.write('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  printer.write(head);
  if (sizeof...(Tail)) printer.write(' ');
  print(forward<Tail>(tail)...);
}

void read() {}
template <class Head, class... Tail>
void read(Head &head, Tail &... tail) {
  scanner.read(head);
  read(tail...);
}
} // namespace fastio
using fastio::print;
using fastio::flush;
using fastio::read;

#define INT(...)   \
  int __VA_ARGS__; \
  read(__VA_ARGS__)
#define LL(...)   \
  ll __VA_ARGS__; \
  read(__VA_ARGS__)
#define STR(...)      \
  string __VA_ARGS__; \
  read(__VA_ARGS__)
#define CHAR(...)   \
  char __VA_ARGS__; \
  read(__VA_ARGS__)
#define DBL(...)      \
  double __VA_ARGS__; \
  read(__VA_ARGS__)

#define VEC(type, name, size) \
  vector<type> name(size);    \
  read(name)
#define VV(type, name, h, w)                     \
  vector<vector<type>> name(h, vector<type>(w)); \
  read(name)

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 2 "library/graph/base.hpp"

template <typename T>
struct Edge {
  int frm, to;
  T cost;
  int id;
};

template <typename T = int, bool directed = false>
struct Graph {
  int N, M;
  using cost_type = T;
  using edge_type = Edge<T>;
  vector<edge_type> edges;
  vector<int> indptr;
  vector<edge_type> csr_edges;
  vc<int> vc_deg, vc_indeg, vc_outdeg;
  bool prepared;

  class OutgoingEdges {
  public:
    OutgoingEdges(const Graph* G, int l, int r) : G(G), l(l), r(r) {}

    const edge_type* begin() const {
      if (l == r) { return 0; }
      return &G->csr_edges[l];
    }

    const edge_type* end() const {
      if (l == r) { return 0; }
      return &G->csr_edges[r];
    }

  private:
    const Graph* G;
    int l, r;
  };

  bool is_prepared() { return prepared; }
  constexpr bool is_directed() { return directed; }

  Graph() : N(0), M(0), prepared(0) {}
  Graph(int N) : N(N), M(0), prepared(0) {}

  void build(int n) {
    N = n, M = 0;
    prepared = 0;
    edges.clear();
    indptr.clear();
    csr_edges.clear();
    vc_deg.clear();
    vc_indeg.clear();
    vc_outdeg.clear();
  }

  void add(int frm, int to, T cost = 1, int i = -1) {
    assert(!prepared);
    assert(0 <= frm && 0 <= to && to < N);
    if (i == -1) i = M;
    auto e = edge_type({frm, to, cost, i});
    edges.eb(e);
    ++M;
  }

  // wt, off
  void read_tree(bool wt = false, int off = 1) { read_graph(N - 1, wt, off); }

  void read_graph(int M, bool wt = false, int off = 1) {
    for (int m = 0; m < M; ++m) {
      INT(a, b);
      a -= off, b -= off;
      if (!wt) {
        add(a, b);
      } else {
        T c;
        read(c);
        add(a, b, c);
      }
    }
    build();
  }

  void build() {
    assert(!prepared);
    prepared = true;
    indptr.assign(N + 1, 0);
    for (auto&& e: edges) {
      indptr[e.frm + 1]++;
      if (!directed) indptr[e.to + 1]++;
    }
    for (int v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
    auto counter = indptr;
    csr_edges.resize(indptr.back() + 1);
    for (auto&& e: edges) {
      csr_edges[counter[e.frm]++] = e;
      if (!directed)
        csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
    }
  }

  OutgoingEdges operator[](int v) const {
    assert(prepared);
    return {this, indptr[v], indptr[v + 1]};
  }

  vc<int> deg_array() {
    if (vc_deg.empty()) calc_deg();
    return vc_deg;
  }

  pair<vc<int>, vc<int>> deg_array_inout() {
    if (vc_indeg.empty()) calc_deg_inout();
    return {vc_indeg, vc_outdeg};
  }

  int deg(int v) {
    if (vc_deg.empty()) calc_deg();
    return vc_deg[v];
  }

  int in_deg(int v) {
    if (vc_indeg.empty()) calc_deg_inout();
    return vc_indeg[v];
  }

  int out_deg(int v) {
    if (vc_outdeg.empty()) calc_deg_inout();
    return vc_outdeg[v];
  }

  void debug() {
    print("Graph");
    if (!prepared) {
      print("frm to cost id");
      for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
    } else {
      print("indptr", indptr);
      print("frm to cost id");
      FOR(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
    }
  }

  vc<int> new_idx;
  vc<bool> used_e;

  // G における頂点 V[i] が、新しいグラフで i になるようにする
  // {G, es}
  pair<Graph<T, directed>, vc<int>> rearrange(vc<int> V) {
    if (len(new_idx) != N) new_idx.assign(N, -1);
    if (len(used_e) != M) used_e.assign(M, 0);
    int n = len(V);
    FOR(i, n) new_idx[V[i]] = i;
    Graph<T, directed> G(n);
    vc<int> es;
    FOR(i, n) {
      for (auto&& e: (*this)[V[i]]) {
        if (used_e[e.id]) continue;
        int a = e.frm, b = e.to;
        if (new_idx[a] != -1 && new_idx[b] != -1) {
          used_e[e.id] = 1;
          G.add(new_idx[a], new_idx[b], e.cost);
          es.eb(e.id);
        }
      }
    }
    FOR(i, n) new_idx[V[i]] = -1;
    for (auto&& eid: es) used_e[eid] = 0;
    G.build();
    return {G, es};
  }

private:
  void calc_deg() {
    assert(vc_deg.empty());
    vc_deg.resize(N);
    for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
  }

  void calc_deg_inout() {
    assert(vc_indeg.empty());
    vc_indeg.resize(N);
    vc_outdeg.resize(N);
    for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
  }
};
#line 3 "library/graph/shortest_path/dijkstra.hpp"

template <typename T, typename GT>
pair<vc<T>, vc<int>> dijkstra_dense(GT& G, int s) {
  const int N = G.N;
  vc<T> dist(N, infty<T>);
  vc<int> par(N, -1);
  vc<bool> done(N);
  dist[s] = 0;
  while (1) {
    int v = -1;
    T mi = infty<T>;
    FOR(i, N) {
      if (!done[i] && chmin(mi, dist[i])) v = i;
    }
    if (v == -1) break;
    done[v] = 1;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[v] + e.cost)) par[e.to] = v;
    }
  }
  return {dist, par};
}

template <typename T, typename GT, bool DENSE = false>
pair<vc<T>, vc<int>> dijkstra(GT& G, int v) {
  if (DENSE) return dijkstra_dense<T>(G, v);
  auto N = G.N;
  vector<T> dist(N, infty<T>);
  vector<int> par(N, -1);
  using P = pair<T, int>;

  priority_queue<P, vector<P>, greater<P>> que;

  dist[v] = 0;
  que.emplace(0, v);
  while (!que.empty()) {
    auto [dv, v] = que.top();
    que.pop();
    if (dv > dist[v]) continue;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[e.frm] + e.cost)) {
        par[e.to] = e.frm;
        que.emplace(dist[e.to], e.to);
      }
    }
  }
  return {dist, par};
}

// 多点スタート。[dist, par, root]
template <typename T, typename GT>
tuple<vc<T>, vc<int>, vc<int>> dijkstra(GT& G, vc<int> vs) {
  assert(G.is_prepared());
  int N = G.N;
  vc<T> dist(N, infty<T>);
  vc<int> par(N, -1);
  vc<int> root(N, -1);

  using P = pair<T, int>;

  priority_queue<P, vector<P>, greater<P>> que;

  for (auto&& v: vs) {
    dist[v] = 0;
    root[v] = v;
    que.emplace(T(0), v);
  }

  while (!que.empty()) {
    auto [dv, v] = que.top();
    que.pop();
    if (dv > dist[v]) continue;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[e.frm] + e.cost)) {
        root[e.to] = root[e.frm];
        par[e.to] = e.frm;
        que.push(mp(dist[e.to], e.to));
      }
    }
  }
  return {dist, par, root};
}
#line 1 "library/flow/maxflow.hpp"
// incremental に辺を追加してよい
template <typename Cap>
struct MaxFlow {
  struct Edge {
    int to, rev;
    Cap cap;
    Cap flow = 0;
  };

  const int N, source, sink;
  vvc<Edge> edges;
  vc<int> prog, level;
  vc<int> que;
  bool calculated;
  Cap flow_ans;

  MaxFlow(int N, int source, int sink)
      : N(N),
        source(source),
        sink(sink),
        edges(N),
        calculated(0),
        flow_ans(0) {}

  void add(int frm, int to, Cap cap, Cap rev_cap = 0) {
    calculated = 0;
    assert(0 <= frm && frm < N);
    assert(0 <= to && to < N);
    assert(frm != to);
    assert(Cap(0) <= cap);
    if (frm == to) return;
    int a = len(edges[frm]);
    int b = len(edges[to]);
    edges[frm].eb(Edge{to, b, cap, 0});
    edges[to].eb(Edge{frm, a, rev_cap, 0});
  }

  // frm, to, flow
  vc<tuple<int, int, Cap>> get_flow_edges() {
    vc<tuple<int, int, Cap>> res;
    FOR(frm, N) {
      for (auto&& e: edges[frm]) {
        if (e.flow <= 0) continue;
        res.eb(frm, e.to, e.flow);
      }
    }
    return res;
  }

  // 差分ではなくこれまでの総量
  Cap flow() {
    if (calculated) return flow_ans;
    calculated = true;
    while (set_level()) {
      prog.assign(N, 0);
      while (1) {
        Cap x = flow_dfs(source, infty<Cap>);
        if (x == 0) break;
        flow_ans += x;
        chmin(flow_ans, infty<Cap>);
        if (flow_ans == infty<Cap>) return flow_ans;
      }
    }
    return flow_ans;
  }

  // 最小カットの値および、カットを表す 01 列を返す
  pair<Cap, vc<int>> cut() {
    flow();
    vc<int> res(N);
    FOR(v, N) res[v] = (level[v] >= 0 ? 0 : 1);
    return {flow_ans, res};
  }

  // O(F(N+M)) くらい使って経路復元
  // simple path になる
  vvc<int> path_decomposition() {
    flow();
    auto edges = get_flow_edges();
    vvc<int> TO(N);
    for (auto&& [frm, to, flow]: edges) { FOR(flow) TO[frm].eb(to); }
    vvc<int> res;
    vc<int> vis(N);

    FOR(flow_ans) {
      vc<int> path = {source};
      vis[source] = 1;
      while (path.back() != sink) {
        int to = POP(TO[path.back()]);
        while (vis[to]) { vis[POP(path)] = 0; }
        path.eb(to), vis[to] = 1;
      }
      for (auto&& v: path) vis[v] = 0;
      res.eb(path);
    }
    return res;
  }

private:
  bool set_level() {
    que.resize(N);
    level.assign(N, -1);
    level[source] = 0;
    int l = 0, r = 0;
    que[r++] = source;
    while (l < r) {
      int v = que[l++];
      for (auto&& e: edges[v]) {
        if (e.cap > 0 && level[e.to] == -1) {
          level[e.to] = level[v] + 1;
          if (e.to == sink) return true;
          que[r++] = e.to;
        }
      }
    }
    return false;
  }

  Cap flow_dfs(int v, Cap lim) {
    if (v == sink) return lim;
    Cap res = 0;
    for (int& i = prog[v]; i < len(edges[v]); ++i) {
      auto& e = edges[v][i];
      if (e.cap > 0 && level[e.to] == level[v] + 1) {
        Cap a = flow_dfs(e.to, min(lim, e.cap));
        if (a > 0) {
          e.cap -= a, e.flow += a;
          edges[e.to][e.rev].cap += a, edges[e.to][e.rev].flow -= a;
          res += a;
          lim -= a;
          if (lim == 0) break;
        }
      }
    }
    return res;
  }
};
#line 2 "library/ds/unionfind/unionfind.hpp"

struct UnionFind {
  int n, n_comp;
  vc<int> dat; // par or (-size)
  UnionFind(int n = 0) { build(n); }

  void build(int m) {
    n = m, n_comp = m;
    dat.assign(n, -1);
  }

  void reset() { build(n); }

  int operator[](int x) {
    while (dat[x] >= 0) {
      int pp = dat[dat[x]];
      if (pp < 0) { return dat[x]; }
      x = dat[x] = pp;
    }
    return x;
  }

  ll size(int x) {
    x = (*this)[x];
    return -dat[x];
  }

  bool merge(int x, int y) {
    x = (*this)[x], y = (*this)[y];
    if (x == y) return false;
    if (-dat[x] < -dat[y]) swap(x, y);
    dat[x] += dat[y], dat[y] = x, n_comp--;
    return true;
  }
};
#line 4 "library/graph/dag_path_cover.hpp"

// 各頂点の色をかえす。各色はひとつのパス上にあるようにする
template <typename DAG>
vc<int> dag_path_cover(DAG& G) {
  assert(G.is_directed());
  for (auto&& e: G.edges) assert(e.frm < e.to);

  int N = G.N;
  int source = 2 * N, sink = 2 * N + 1;
  MaxFlow<int> F(2 * N + 2, source, sink);
  FOR(v, N) {
    F.add(source, 2 * v + 1, 1);
    F.add(2 * v + 0, sink, 1);
    F.add(2 * v + 0, 2 * v + 1, infty<int>);
  }
  for (auto&& e: G.edges) F.add(2 * e.frm + 1, 2 * e.to + 0, infty<int>);

  F.flow();
  auto paths = F.path_decomposition();

  UnionFind uf(N);
  for (auto& P: paths) {
    int a = P[1], b = P[len(P) - 2];
    uf.merge(a / 2, b / 2);
  }

  vc<int> ANS(N, -1);
  int p = 0;
  FOR(v, N) if (uf[v] == v) ANS[v] = p++;
  FOR(v, N) if (uf[v] != v) ANS[v] = ANS[uf[v]];
  return ANS;
};
#line 1 "library/ds/fastset.hpp"
/* 64分木。
insert, erase
[]での存在判定
next, prev
*/
struct FastSet {
  using uint = unsigned;
  using ull = unsigned long long;

  int bsr(ull x) { return 63 - __builtin_clzll(x); }
  int bsf(ull x) { return __builtin_ctzll(x); }

  static constexpr uint B = 64;
  int n, lg;
  vector<vector<ull>> seg;
  FastSet(int _n) : n(_n) {
    do {
      seg.push_back(vector<ull>((_n + B - 1) / B));
      _n = (_n + B - 1) / B;
    } while (_n > 1);
    lg = int(seg.size());
  }
  bool operator[](int i) const { return (seg[0][i / B] >> (i % B) & 1) != 0; }
  void insert(int i) {
    for (int h = 0; h < lg; h++) {
      seg[h][i / B] |= 1ULL << (i % B);
      i /= B;
    }
  }
  void add(int i) { insert(i); }
  void erase(int i) {
    for (int h = 0; h < lg; h++) {
      seg[h][i / B] &= ~(1ULL << (i % B));
      if (seg[h][i / B]) break;
      i /= B;
    }
  }
  void remove(int i) { erase(i); }

  // x以上最小の要素を返す。存在しなければ n。
  int next(int i) {
    chmax(i, 0);
    if (i >= n) return n;
    for (int h = 0; h < lg; h++) {
      if (i / B == seg[h].size()) break;
      ull d = seg[h][i / B] >> (i % B);
      if (!d) {
        i = i / B + 1;
        continue;
      }
      // find
      i += bsf(d);
      for (int g = h - 1; g >= 0; g--) {
        i *= B;
        i += bsf(seg[g][i / B]);
      }
      return i;
    }
    return n;
  }

  // x以下最大の要素を返す。存在しなければ -1。
  int prev(int i) {
    if (i < 0) return -1;
    if (i >= n) i = n - 1;
    for (int h = 0; h < lg; h++) {
      if (i == -1) break;
      ull d = seg[h][i / B] << (63 - i % 64);
      if (!d) {
        i = i / B - 1;
        continue;
      }
      // find
      i += bsr(d) - (B - 1);
      for (int g = h - 1; g >= 0; g--) {
        i *= B;
        i += bsr(seg[g][i / B]);
      }
      return i;
    }
    return -1;
  }

  // [l, r)
  template <typename F>
  void enumerate(int l, int r, F f) {
    int x = l - 1;
    while (1) {
      x = next(x + 1);
      if (x >= r) break;
      f(x);
    }
  }

  void debug() {
    string s;
    for (int i = 0; i < n; ++i) s += ((*this)[i] ? '1' : '0');
    print(s);
  }
};
#line 3 "library/graph/toposort.hpp"

// 辞書順最小の toposort を返す
template <typename GT>
vc<int> toposort(GT& G) {
  assert(G.is_prepared() && G.is_directed());
  const int N = G.N;
  auto [indeg, outdeg] = G.deg_array_inout();
  FastSet que(N);
  vc<int> V;
  FOR(v, N) if (indeg[v] == 0) que.insert(v);
  while (1) {
    int v = que.next(0);
    if (v == N) break;
    que.erase(v), V.eb(v);
    for (auto&& e: G[v]) {
      if (--indeg[e.to] == 0) que.insert(e.to);
    }
  }
  return (len(V) < N ? vc<int>{} : V);
}
#line 7 "main.cpp"

void solve(ll N, ll M, ll L) {
  vv(ll, dist, N, N);
  {
    Graph<ll> G(N);
    G.read_graph(M, 1, 0);
    FOR(v, N) { dist[v] = dijkstra<ll>(G, v).fi; }
  }
  VEC(pi, PT, L);
  N = L;
  Graph<int, 1> G(N);
  FOR(a, N) FOR(b, N) {
    if (a == b) continue;
    auto [pa, ta] = PT[a];
    auto [pb, tb] = PT[b];
    if (ta + dist[pa][pb] <= tb) G.add(a, b);
  }
  G.build();

  auto V = toposort(G);
  G = G.rearrange(V).fi;

  auto color = dag_path_cover(G);
  print(MAX(color) + 1);
}

signed main() {
  while (1) {
    LL(N, M, L);
    if (N + M + L == 0) break;
    solve(N, M, L);
  }

  return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 59984
final_rank: 18

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);


// Bipartite Matching (Simple)
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_7_A&lang=ja
// 蟻本 p. 197


int V, E;
int X, Y;
vector<int> G[MAX_N];
int match[MAX_N];
bool used[MAX_N];

// uとvを結ぶ辺をグラフに追加する
void add_edge(int u, int v) {
	G[u].push_back(v);
	G[v].push_back(u);
}

// 増加パスをDFSで探す
bool dfs(int v) {
	used[v] = true;
	for (int i = 0; i < G[v].size(); i++) {
		int u = G[v][i];
		int w = match[u];
		if (w < 0 || !used[w] && dfs(w)) {
			match[v] = u;
			match[u] = v;
			return true;
		}
	}
	return false;
}

int bipartite_matching() {
	int res = 0;
	memset(match, -1, sizeof(match));
	for (int v = 0; v < V; v++) {
		if (match[v] < 0) {
			memset(used, 0, sizeof(used));
			if (dfs(v)) {
				res++;
			}
		}
	}
	return res;
}

int N, M, L;
long long cost[110][110];
int a[1100], b[1100];
long long c[1100];
int p[1100];
long long t[1100];

int main() {
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	while (cin >> N >> M >> L) {
		if (N == 0 && M == 0 && L == 0) {
			break;
		}

		for (int i = 0; i < M; i++) {
			cin >> a[i] >> b[i] >> c[i];
		}
		for (int i = 0; i < L; i++) {
			cin >> p[i] >> t[i];
		}


		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				cost[i][j] = LINF;
			}
			cost[i][i] = 0;
		}

		for (int i = 0; i < M; i++) {
			cost[a[i]][b[i]] = c[i];
			cost[b[i]][a[i]] = c[i];
		}


		for (int k = 0; k < N; k++) {
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);
				}
			}
		}

		V = 2 * L;
		for (int i = 0; i < V; i++) {
			G[i].clear();
		}

		for (int i = 0; i < L; i++) {
			for (int j = 0; j < L; j++) {
				if (i == j) {
					continue;
				}

				if (t[i] + cost[p[i]][p[j]] <= t[j]) {
					add_edge(i, j + L);
				}
			}
		}


		cout << L - bipartite_matching() << endl;


	}

	return 0;
}
accuracy: 1
time_ms: 1410
memory_kb: 68376
final_rank: 20

code_snippet: #include "bits/stdc++.h"
using namespace std;
using namespace std::chrono;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
#define REP(i, n) for(int i = 0;i < (n);i++)
/*cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);*/
const int mod=1000000007;
const llint inf=2.19e15+1;
const long double pai=3.141592653589793238462643383279502884197;
const long double eps=1e-10;
template <class T,class U>bool chmin(T& a,U b){if(a>b){a=b;return true;}return false;}
template <class T,class U>bool chmax(T& a,U b){if(a<b){a=b;return true;}return false;}
llint gcd(llint a,llint b){if(a%b==0){return b;}else return gcd(b,a%b);}
llint lcm(llint a,llint b){if(a==0){return b;}return a/gcd(a,b)*b;}
template<class T> void SO(T& ve){sort(ve.begin(),ve.end());}
template<class T> void REV(T& ve){reverse(ve.begin(),ve.end());}
template<class T>int LBI(const vector<T>&ar,T in){return lower_bound(ar.begin(),ar.end(),in)-ar.begin();}
template<class T>int UBI(const vector<T>&ar,T in){return upper_bound(ar.begin(),ar.end(),in)-ar.begin();}

#include <algorithm>
#include <cassert>
#include <limits>
#include <queue>
#include <vector>

template <class T> struct simple_queue {
    std::vector<T> payload;
    int pos = 0;
    void reserve(int n) { payload.reserve(n); }
    int size() const { return int(payload.size()) - pos; }
    bool empty() const { return pos == int(payload.size()); }
    void push(const T& t) { payload.push_back(t); }
    T& front() { return payload[pos]; }
    void clear() {
        payload.clear();
        pos = 0;
    }
    void pop() { pos++; }
};
	
template <class Cap> struct mf_graph {
  public:
    mf_graph() : _n(0) {}
    mf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        assert(0 <= cap);
        int m = int(pos.size());
        pos.push_back({from, int(g[from].size())});
        int from_id = int(g[from].size());
        int to_id = int(g[to].size());
        if (from == to) to_id++;
        g[from].push_back(_edge{to, to_id, cap});
        g[to].push_back(_edge{from, from_id, 0});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
    };

    edge get_edge(int i) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    std::vector<edge> edges() {
        int m = int(pos.size());
        std::vector<edge> result;
        for (int i = 0; i < m; i++) {
            result.push_back(get_edge(i));
        }
        return result;
    }
    void change_edge(int i, Cap new_cap, Cap new_flow) {
        int m = int(pos.size());
        assert(0 <= i && i < m);
        assert(0 <= new_flow && new_flow <= new_cap);
        auto& _e = g[pos[i].first][pos[i].second];
        auto& _re = g[_e.to][_e.rev];
        _e.cap = new_cap - new_flow;
        _re.cap = new_flow;
    }

    Cap flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    Cap flow(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);

        std::vector<int> level(_n), iter(_n);
        simple_queue<int> que;

        auto bfs = [&]() {
            std::fill(level.begin(), level.end(), -1);
            level[s] = 0;
            que.clear();
            que.push(s);
            while (!que.empty()) {
                int v = que.front();
                que.pop();
                for (auto e : g[v]) {
                    if (e.cap == 0 || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    if (e.to == t) return;
                    que.push(e.to);
                }
            }
        };
        auto dfs = [&](auto self, int v, Cap up) {
            if (v == s) return up;
            Cap res = 0;
            int level_v = level[v];
            for (int& i = iter[v]; i < int(g[v].size()); i++) {
                _edge& e = g[v][i];
                if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                Cap d =
                    self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                if (d <= 0) continue;
                g[v][i].cap += d;
                g[e.to][e.rev].cap -= d;
                res += d;
                if (res == up) break;
            }
            return res;
        };

        Cap flow = 0;
        while (flow < flow_limit) {
            bfs();
            if (level[t] == -1) break;
            std::fill(iter.begin(), iter.end(), 0);
            while (flow < flow_limit) {
                Cap f = dfs(dfs, t, flow_limit - flow);
                if (!f) break;
                flow += f;
            }
        }
        return flow;
    }

    std::vector<bool> min_cut(int s) {
        std::vector<bool> visited(_n);
        simple_queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            visited[p] = true;
            for (auto e : g[p]) {
                if (e.cap && !visited[e.to]) {
                    visited[e.to] = true;
                    que.push(e.to);
                }
            }
        }
        return visited;
    }

  private:
    int _n;
    struct _edge {
        int to, rev;
        Cap cap;
    };
    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};



int main(void){
	while(-1){
		int i,j,k,n,m,L;cin>>n>>m>>L;
		if(n==0){break;}
		int dist[100][100];
		for(i=0;i<n;i++){
			for(j=0;j<n;j++){
				dist[i][j]=mod;
			}
			dist[i][i]=0;
		}
		for(i=0;i<m;i++){
			int u,v,d;cin>>u>>v>>d;
			chmin(dist[u][v],d);
			chmin(dist[v][u],d);
		}
		for(j=0;j<n;j++){
			for(i=0;i<n;i++){
				for(k=0;k<n;k++){
					chmin(dist[i][k],dist[i][j]+dist[j][k]);
				}
			}
		}
		vector<pair<int,int>>req(L);
		for(i=0;i<L;i++){
			cin>>req[i].sec>>req[i].fir;
		}
		SO(req);
		mf_graph<int> gra(L+L+2);
		for(i=0;i<L;i++){
			for(j=i+1;j<L;j++){
				if(req[i].fir+dist[req[i].sec][req[j].sec]<=req[j].fir){
					gra.add_edge(i,j+L,1);
				}
			}
			gra.add_edge(L+L,i,1);
			gra.add_edge(i+L,L+L+1,1);
		}
		cout<<L-gra.flow(L+L,L+L+1)<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 22744
final_rank: 9