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;
template <typename _typer>
inline _typer read() {
  _typer init = 0;
  char ch = getchar(), k = 0;
  for (; !isdigit(ch); ch = getchar()) k = (ch == '-');
  for (; isdigit(ch); ch = getchar())
    init = (init << 3) + (init << 1) + (ch ^ 48);
  return k ? -init : init;
}
const long long N = 100005, INF = 1e9;
int n, m;
struct EDGE {
  int to, nex, cost;
} edge[N << 1];
int head[N], cntedge, In[N];
void Addedge(int u, int v, int w) {
  edge[++cntedge] = (EDGE){v, head[u], w};
  head[u] = cntedge, ++In[v];
}
struct FenwickTree {
  int c[N];
  void Init() { memset(c, 0, sizeof c); }
  void Add(int x) {
    for (; x <= n; x += x & -x) c[x] += 1;
  }
  int Que(int x) {
    int res = 0;
    for (; x > 0; x -= x & -x) res += c[x];
    return res;
  }
} Bit;
int Mxw, root;
int Valid[N], Mx[N], mx[N], CntNode[N];
int mark[N], used[N], Wei[2][N];
void BuiltTree(int u, int fa) {
  for (int i = head[u], v; i; i = edge[i].nex) {
    v = edge[i].to;
    if (v == fa) continue;
    BuiltTree(v, u);
    Valid[u] += Valid[v];
    if (Valid[v])
      Mx[u] = max(Mx[u], Mx[v] + edge[i].cost);
    else
      --In[u];
  }
}
void BuiltNewTree(int u, int fa, int w) {
  Mx[u] = mx[u] = 0;
  for (int i = head[u], v; i; i = edge[i].nex) {
    v = edge[i].to;
    if (v == fa || !Valid[v]) continue;
    BuiltNewTree(v, u, w + edge[i].cost);
    int tmp = Mx[v] + edge[i].cost;
    if (tmp > Mx[u])
      mx[u] = Mx[u], Mx[u] = tmp;
    else if (tmp > mx[u])
      mx[u] = tmp;
  }
  if (w > Mxw) root = u, Mxw = w;
}
void CalcSonTree(int u, int fa, int w, int opt) {
  for (int i = head[u], v; i; i = edge[i].nex) {
    v = edge[i].to;
    if (v == fa || !Valid[v]) continue;
    CalcSonTree(v, u, w + edge[i].cost, opt);
    if (Mx[v] + edge[i].cost == Mx[u])
      if (w + edge[i].cost > Mx[v])
        if ((opt == 0 && w >= mx[u]) || (opt && w > mx[u]))
          Wei[opt][u] += Wei[opt][v];
    if (Mx[v] + edge[i].cost != Mx[u])
      if (w + edge[i].cost > Mx[v])
        if ((opt == 0 && w >= Mx[u]) || (opt && w > Mx[u]))
          Wei[opt][u] += Wei[opt][v];
  }
  if (used[u]) ++Wei[opt][u];
}
void GetIntersection(int u, int fa) {
  ++mark[u];
  int Count = 0;
  for (int i = head[u], v; i; i = edge[i].nex) {
    v = edge[i].to;
    if (v == fa || !Valid[v]) continue;
    if (Mx[u] == Mx[v] + edge[i].cost) ++Count;
  }
  if (Count != 1) return;
  for (int i = head[u], v; i; i = edge[i].nex) {
    v = edge[i].to;
    if (v == fa || !Valid[v]) continue;
    if (Mx[u] == Mx[v] + edge[i].cost) GetIntersection(v, u);
  }
}
int main() {
  n = read<int>(), m = read<int>();
  for (register int i = (1), iend = (m); i <= iend; ++i) {
    root = read<int>();
    used[root] = Valid[root] = 1;
  }
  for (register int i = (2), iend = (n); i <= iend; ++i) {
    int x = read<int>(), y = read<int>(), z = read<int>();
    Addedge(x, y, z);
    Addedge(y, x, z);
  }
  int rt = 1;
  BuiltTree(rt, 0);
  BuiltNewTree(rt, 0, 0);
  Mxw = 0, rt = root;
  BuiltNewTree(rt, 0, 0);
  CalcSonTree(rt, 0, 0, 0);
  GetIntersection(rt, 0);
  Mxw = 0, rt = root;
  BuiltNewTree(rt, 0, 0);
  CalcSonTree(rt, 0, 0, 1);
  GetIntersection(rt, 0);
  int Ans1 = 0, Ans2 = 0;
  for (register int i = (1), iend = (n); i <= iend; ++i)
    if (mark[i] == 2 && !used[i]) {
      if (Ans1 < Wei[0][i] + Wei[1][i]) {
        Ans1 = Wei[0][i] + Wei[1][i];
        Ans2 = 1;
      } else if (Ans1 == Wei[0][i] + Wei[1][i])
        ++Ans2;
    }
  cout << Ans1 << " " << Ans2 << endl;
  return 0;
}
