7 3
1 4 7
1 2 2
2 3 3
3 4 8
2 5 1
1 6 4
6 7 5
 10 2
1 5
5 3 2
8 4 8
7 6 9
7 10 1
10 1 4
9 5 1
5 8 2
7 2 9
6 5 6
 10 5
4 8 7 5 1
5 1 1
2 7 1
4 3 1
10 9 1
10 1 1
1 8 1
10 7 1
10 3 1
7 6 1
 10 9
9 7 6 10 3 5 2 8 1
9 4 10
10 8 3
3 6 2
5 1 8
5 2 5
1 10 10
6 7 1
9 1 7
1 6 3
 10 5
8 5 2 10 1
3 1 7
5 4 6
10 8 4
6 8 9
7 8 4
9 5 6
8 1 9
2 10 2
9 8 7

3 2
 2 3
 5 1
 0 1
 5 1

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct node {
  int dist, Min, Max;
  node(long long dist = 0, int Min = 0, int Max = 0)
      : dist(dist), Min(Min), Max(Max) {}
};
node ST[4 * maxn];
int lazy[4 * maxn];
vector<pair<int, int>> adj[maxn];
int rmq[maxn][19], depth[maxn];
int N, M;
bool have[maxn];
int dist[maxn];
int tin[maxn], tout[maxn];
vector<int> chain;
int res[maxn], order[maxn];
node merges(const node& x, const node& y) {
  if (x.dist != y.dist) {
    return (x.dist < y.dist) ? y : x;
  } else {
    node res;
    res.dist = x.dist;
    res.Min = (tin[x.Min] < tin[y.Min]) ? x.Min : y.Min;
    res.Max = (tout[x.Max] < tout[y.Max]) ? y.Max : x.Max;
    return res;
  }
  assert(0);
}
void build(int id, int l, int r) {
  if (l == r) {
    if (have[order[l]])
      ST[id].dist = dist[order[l]];
    else
      ST[id].dist = -1e9;
    ST[id].Min = ST[id].Max = order[l];
    return;
  }
  int mid = (l + r) / 2;
  build(id << 1, l, mid);
  build(id << 1 | 1, mid + 1, r);
  ST[id] = merges(ST[id << 1], ST[id << 1 | 1]);
}
void dolazy(int id, int l, int r) {
  ST[id].dist += lazy[id];
  if (l != r) {
    lazy[id << 1] += lazy[id];
    lazy[id << 1 | 1] += lazy[id];
  }
  lazy[id] = 0;
}
void update(int id, int l, int r, int L, int R, int v) {
  dolazy(id, l, r);
  if (l > R || L > r) return;
  if (L <= l && r <= R) {
    ST[id].dist += v;
    if (l != r) {
      lazy[id << 1] += v;
      lazy[id << 1 | 1] += v;
    }
    return;
  }
  int mid = (l + r) / 2;
  update(id << 1, l, mid, L, R, v);
  update(id << 1 | 1, mid + 1, r, L, R, v);
  ST[id] = merges(ST[id << 1], ST[id << 1 | 1]);
}
int getmax(int id, int l, int r, int L, int R) {
  dolazy(id, l, r);
  if (l > R || L > r) return -1e9;
  if (L <= l && r <= R) return ST[id].dist;
  int mid = (l + r) / 2;
  return max(getmax(id << 1, l, mid, L, R),
             getmax(id << 1 | 1, mid + 1, r, L, R));
}
int Time = 0;
void precalc(int u = 1, int p = -1) {
  for (int i = 1; (1 << i) <= N; ++i) {
    rmq[u][i] = rmq[rmq[u][i - 1]][i - 1];
  }
  tin[u] = ++Time;
  order[Time] = u;
  for (auto v : adj[u]) {
    if (v.first == p) continue;
    dist[v.first] = dist[u] + v.second;
    rmq[v.first][0] = u;
    depth[v.first] = depth[u] + 1;
    precalc(v.first, u);
  }
  tout[u] = Time;
}
bool par(int u, int v) { return tin[u] <= tin[v] && tout[v] <= tout[u]; }
int LCA(int x, int y) {
  if (depth[x] < depth[y]) swap(x, y);
  if (par(y, x)) return y;
  for (int k = 18; k >= 0; --k) {
    if (depth[rmq[x][k]] >= depth[y]) {
      x = rmq[x][k];
    }
  }
  for (int k = 18; k >= 0; --k) {
    if (rmq[x][k] != rmq[y][k]) {
      x = rmq[x][k];
      y = rmq[y][k];
    }
  }
  return (x == y) ? x : rmq[x][0];
}
void change(int u, int v) {
  int lc = LCA(u, v);
  res[u]++;
  res[v]++;
  res[lc]--;
  res[rmq[lc][0]]--;
}
bool Have(int u) {
  node val = ST[1];
  return (getmax(1, 1, N, tin[u], tout[u]) == val.dist);
}
void solve(int u = 1, int p = -1) {
  for (auto v : adj[u]) {
    if (v.first == p) continue;
    update(1, 1, N, tin[v.first], tout[v.first], -2 * v.second);
    update(1, 1, N, 1, N, v.second);
    chain.push_back(v.first);
    if (have[v.first]) {
      node val = ST[1];
      int p = LCA(val.Min, val.Max);
      if (par(p, v.first)) {
        int l = 0, r = chain.size() - 1, mid;
        while (l <= r) {
          mid = (l + r) / 2;
          if (Have(chain[mid]))
            l = mid + 1;
          else
            r = mid - 1;
        }
        change(v.first, chain[l - 1]);
      } else {
        change(p, v.first);
      }
    }
    solve(v.first, u);
    chain.pop_back();
    update(1, 1, N, tin[v.first], tout[v.first], 2 * v.second);
    update(1, 1, N, 1, N, -v.second);
  }
}
void dfs(int u = 1, int p = -1) {
  for (auto& v : adj[u]) {
    if (v.first == p) continue;
    dfs(v.first, u);
    res[u] += res[v.first];
  }
}
void output(void) {
  int ans = 0, cnt = 0;
  for (int i = 1; i <= N; ++i) {
    if (have[i] == false) {
      if (res[i] > ans)
        ans = res[i], cnt = 1;
      else if (res[i] == ans)
        ++cnt;
    }
  }
  cout << ans << ' ' << cnt << '\n';
}
signed main(void) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  if (fopen("A.INP", "r")) {
    freopen("A.INP", "r", stdin);
    freopen("A.OUT", "w", stdout);
  }
  cin >> N >> M;
  for (int i = 1; i <= M; ++i) {
    int x;
    cin >> x;
    have[x] = true;
  }
  for (int i = 1; i < N; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    adj[u].push_back(make_pair(v, w));
    adj[v].push_back(make_pair(u, w));
  }
  depth[1] = 1;
  precalc();
  build(1, 1, N);
  if (have[1]) {
    node x = ST[1];
    int p = LCA(x.Min, x.Max);
    change(1, p);
  }
  chain.push_back(1);
  solve();
  dfs();
  output();
}
