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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(LCA(0));
	int totalSum = remainingTreeSum(topnode);
	debug2(topnode, totalSum);

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	rep(i,n) debug3(i, depthIndex[i], depth[i]);

	debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	printf("\n");
	rep(i,n) debug3(i, depthIndex[i], depth[i]);
	debug(depthIndex[end1]);

	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

bool test = false;

void dfs(int x)
{
	if (test) cout << x << " ::: dfsfs \n";
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		if (n == 256) cout << x << " ::: \n";
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	if (n == 256) test = true;
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << depth[end1] << endl;
	int x = end1;
	if (depthIndex[end1] < x) x = depthIndex[end1];
	if (n == 256) cout << x << " faf df \n";
	cout << x + 1 << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

bool test = false;

void dfs(int x)
{
	if (test) cout << x << " ::: dfsfs \n";
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		if (n == 256) cout << x << " ::: \n";
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	test = true;
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << depth[end1] << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		if (n == 256) cout << x << " ::: \n";
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << depth[end1] << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << depth[end1] << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = 0, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == 0) depthIndex[x] = x;
	else depthIndex[x] = index;
	return depth[x] = d;
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(LCA(0));
	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	findDepth(topnode);
	int end1 = depthIndex[topnode];
	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);
	// debug(depthIndex[end1]);
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N], parent[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			parent[edges[x][i]] = x;
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = 0, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);
		if (d <= y)
		{
			if (d == y)
			{
				index = min(index, depthIndex[child[x][i]]);
			}
			else
			{
				d = y;
				index = depthIndex[child[x][i]];
			}
		}
	}
	if (d == 0) depthIndex[x] = x;
	else depthIndex[x] = index;
	return depth[x] = d;
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	parent[0] = -1;
	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(LCA(0));
	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	findDepth(topnode);
	int end1 = depthIndex[topnode];
	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	rep(i, n)
	{
		rep(j, child[i].size())
		{
			if (parent[topnode] != -1)
			{
				if (i == parent[topnode] and child[i][j] == topnode)
				{
					continue;
				}
			}
			edges[i].pb(child[i][j]);
			edges[child[i][j]].pb(i);
		}
	}
	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);
	// debug(depthIndex[end1]);
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

bool test = false;

void dfs(int x)
{
	if (test) cout << x << " ::: dfsfs \n";
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		if (n == 256) cout << x << " ::: \n";
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	if (n == 256) test = true;
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	if (n == 256) cout << topnode << " " <<  end1 << " " << depthIndex[end1] << " " << totalSum <<  " " << depth[end1] << endl;
	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

// bool test = false;

void dfs(int x)
{
	// if (test) cout << x << " ::: dfsfs \n";
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		// if (n == 256) cout << x << " ::: \n";
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(topnode);
	// printgraph(end1);

	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	// cout << topnode << " " << totalSum << endl;

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);
	int x = end1;
	if (depthIndex[end1] < x) x = depthIndex[end1];
	cout << x + 1 << "\n" << 2*totalSum - depth[end1] << endl;
}


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

#define ll long long
#define rep(i,n) for(int i=0; i<(n); i++)
#define forn(i,a,b) for(int i=(a); i<=(b); i++)
#define forb(i,a,b) for(int i=(a); i>=(b); i--)

#define DBG 1
#define debug(x) if (DBG) {cerr << #x << " : " << x << endl; }
#define debug2(x, y) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << endl; }
#define debug3(x, y, z) if (DBG) {cerr << #x << " : " << x << " :: " << #y << " : " << y << " :: " << #z << " : " << z << endl; }

#define pb push_back
#define mp make_pair
#define pi pair<int, int>
#define pl pair<ll, ll>
#define VI vector<int>
#define VII vector<VI >
#define VL vector<ll>

#define all(x) x.begin(), x.end()
#define max(a,b) ((a) > (b)) ? (a) : (b)
#define min(a,b) ((a) < (b)) ? (a) : (b)

#define si(x) scanf("%i", &x)
#define sd(x) scanf("%lf", &x)

// #define gc getchar_unlocked
// void getint(int &x)
// {
//     register int c = gc();
//     x = 0;
//     for(;(c<48 || c>57);c = gc());
//     for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
// }

#define N 183456

VI edges[N], child[N];
// set<int> :: iterator itr;

bool attacked[N], visited[N];

int n, m;

int subtreeAttacks[N];

void dfs(int x)
{
	visited[x] = true;
	rep(i, edges[x].size())
	{
		if (!visited[edges[x][i]])
		{
			child[x].pb(edges[x][i]);
			dfs(edges[x][i]);
		}
	}
}

void computesubtree(int x)
{
	int y = attacked[x];
	rep(i, child[x].size())
	{
		computesubtree(child[x][i]);
		y += subtreeAttacks[child[x][i]];
	}
	subtreeAttacks[x] = y;
}

int LCA(int x)
{
	rep(i, child[x].size())
	{
		if (subtreeAttacks[x] == subtreeAttacks[child[x][i]])
		{
			return LCA(child[x][i]);
		}
	}
	return x;
}

int chopTree(int x)
{
	VI newChild;
	rep(i, child[x].size())
	{
		if (subtreeAttacks[child[x][i]] > 0)
		{
			chopTree(child[x][i]);
			newChild.pb(child[x][i]);
		}
	}
	child[x] = newChild;
}

int remainingTreeSum(int x)
{
	int sum = 0;
	rep(i, child[x].size())
	{
		sum += 1 + remainingTreeSum(child[x][i]);
	}
	return sum;
}

int depth[N], depthIndex[N];

int findDepth(int x)
{
	int d = -1, index = N;
	rep(i, child[x].size())
	{
		int y = 1 + findDepth(child[x][i]);

		if (d == y)
		{
			index = min(index, depthIndex[child[x][i]]);
		}
		else if (d < y)
		{
			d = y;
			index = depthIndex[child[x][i]];
		}
	}
	if (d == -1)
	{
		depthIndex[x] = x;
		depth[x] = 0;
	}
	else
	{
		depthIndex[x] = index;
		depth[x] = d;
	}
	return depth[x];
}

void makeBidirected(int x)
{
	rep(i, child[x].size())
	{
		makeBidirected(child[x][i]);
		edges[x].pb(child[x][i]);
		edges[child[x][i]].pb(x);
	}
}

int main()
{
	cin >> n >>  m;
	rep(i, n-1)
	{
		int x, y;
		cin >> x >> y;
		edges[x-1].pb(y-1);
		edges[y-1].pb(x-1);
	}

	rep(i, m)
	{
		int x;
		cin >> x;
		attacked[x-1] = true;
	}

	dfs(0);
	computesubtree(0);

	int topnode = LCA(0);
	chopTree(LCA(0));
	int totalSum = remainingTreeSum(topnode);
	// debug2(topnode, totalSum);

	findDepth(topnode);
	int end1 = depthIndex[topnode];

	// rep(i,n) debug3(i, depthIndex[i], depth[i]);

	// debug3(topnode, totalSum, end1);

	rep(i, n) edges[i].clear();

	makeBidirected(topnode);

	rep(i, n) child[i].clear();

	memset(visited, false, sizeof visited);
	dfs(end1);

	findDepth(end1);

	// printf("\n");
	// rep(i,n) debug3(i, depthIndex[i], depth[i]);
	// debug(depthIndex[end1]);

	cout << (min(end1, depthIndex[end1]) + 1) << "\n" << 2*totalSum - depth[end1] << endl;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    freopen("592D.inp","r",stdin);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = N, res2 = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p[N], sum = 0;
vector< int> c[N];

void dfs( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) child = a[u] = 1;
        else continue;

        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p[u] = min( p[u], p[v]);
            }
            else {
                if (f1[v] + 1 == f2[u]) p[u] = min( p[u], p[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p[u] = p[v];
            }
    }
    sum += a[u];
    if (child) return;
    p[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    int root = 0;
    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1, root = x;

    fill( p + 1, p + n + 1, n + 1);
    dfs( 0, root);

    int res1 = min( root, p[root]), res2 = f1[root];
    for(int i = 1; i <= n; i ++)
    {
        if (!a[i] || !f2[i]) continue;

        int w = f1[i] + f2[i];

        if (w == res2) res1 = min( res1, p[i]);
        if (w > res2 ) res1 = p[i], res2 = w;
    }

    cout << res1 << endl << (1ll * (sum - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
    p2[u] = 0;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = N, res2 = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
    p2[u] = 0;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = 0, res2 = -1;
    for(int i = 1; i <= n; i ++)
    if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
    p1[v] = 0;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = N, res2 = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = 0, res2 = 0;
    for(int i = 1; i <= n; i ++)
        if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N];
vector< int> c[N];

void dfs( int par, int u)
{
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) a[u] = 1;
    }
}

void dfsdp( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        if (!a[v]) continue;
        dfsdp( u, v);
        child = 1;
        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1;

    int root = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i]) {
        root = i;
        break;
    }

    dfs( 0, root);
    dfsdp( 0, root);

    int dem = 0, res1 = N, res2 = 0;
    for(int i = 1; i <= n; i ++)
    if (a[i])
    {
        dem ++;
        int w = f1[i] + f2[i];
        int node;

        if (p2[i]) node = min( p1[i], p2[i]);
        else node = min( p1[i], i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (dem - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p[N], sum = 0;
vector< int> c[N];

void dfs( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) child = a[u] = 1;
        else continue;

        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                if (f1[v] + 1 == f1[u]) p[u] = min( p[u], p[v]);
                else p[u] = p[v];
            }
        else {
            if (f1[v] + 1 == f2[u]) p[u] = min( p[u], p[v]);
            if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p[u] = p[v];
        }
    }
    sum += a[u];
    if (child) return;
    p[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    int root = 0;
    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1, root = x;

    fill( p + 1, p + n + 1, n + 1);
    dfs( 0, root);

    int res1 = min( root, p[root]), res2 = f1[root];
    for(int i = 1; i <= n; i ++)
    {
        if (!a[i] || !f2[i]) continue;

        int w = f1[i] + f2[i];

        if (w == res2) res1 = min( res1, p[i]);
        if (w > res2 ) res1 = p[i], res2 = w;
    }

    cout << res1 << endl << (1ll * (sum - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N], sum = 0;
vector< int> c[N];

void dfs( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) child = a[u] = 1;
        else continue;

        if (f1[v] + 1 > f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
        else {
            if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
            if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
        }
    }
    sum += a[u];
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    //freopen("592D.inp","r",stdin);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    int root = 0;
    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1, root = x;

    dfs( 0, root);

    int res1 = min( root, p1[root]), res2 = f1[root];
    for(int i = 1; i <= n; i ++)
    {
        if (!a[i] || !f2[i]) continue;

        int w = f1[i] + f2[i];
        int node = min( p1[i], p2[i]);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (sum - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N], sum = 0;
vector< int> c[N];

void dfs( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) child = a[u] = 1;
        else continue;

        if (f1[v] + 1 > f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
        else {
            if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
            if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
        }
        if (f1[u] == f2[u] && p1[u] > p2[u]) swap( p1[u], p2[u]);
    }
    sum += a[u];
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    int root = 0;
    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1, root = x;

    dfs( 0, root);

    int res1 = 0, res2 = -1;
    for(int i = 1; i <= n; i ++)
    {
        if (!a[i]) continue;

        int w = f1[i] + f2[i];
        int node = p1[i];
        if (f2[i]) node = min( node, p2[i]);
        else node = min( node, i);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (sum - 1) * 2 - res2);

    return 0;
}


#include <bits/stdc++.h>
#define PB(x) push_back(x)
using namespace std;

const int N = 200005;

int n, m, a[N], f1[N], f2[N], p1[N], p2[N], sum = 0;
vector< int> c[N];

void dfs( int par, int u)
{
    bool child = 0;
    for(int i = 0; i < c[u].size(); i ++)
    {
        int v = c[u][i];
        if (v == par) continue;
        dfs( u, v);
        if (a[v]) child = a[u] = 1;
        else continue;

        if (f1[v] + 1 >= f1[u]) {
                f2[u] = f1[u];
                f1[u] = f1[v] + 1;

                p2[u] = p1[u];
                p1[u] = p1[v];
            }
            else {
                if (f1[v] + 1 == f2[u]) p2[u] = min( p2[u], p1[v]);
                if (f1[v] + 1 > f2[u]) f2[u] = f1[v] + 1, p2[u] = p1[v];
            }
    }
    sum += a[u];
    if (child) return;
    p1[u] = u;
}

int main()
{
    ios_base::sync_with_stdio(0);

    cin >> n >> m;
    for(int i = 1; i < n; i ++)
    {
        int u, v;
        cin >> u >> v;
        c[u].PB(v);
        c[v].PB(u);
    }

    int root = 0;
    for(int i = 1, x; i <= m; i ++) cin >> x, a[x] = 1, root = x;

    dfs( 0, root);

    int res1 = min( root, p1[root]), res2 = f1[root];
    for(int i = 1; i <= n; i ++)
    {
        if (!a[i] || !f2[i]) continue;

        int w = f1[i] + f2[i];
        int node = min( p1[i], p2[i]);

        if (w == res2) res1 = min( res1, node);
        if (w > res2 ) res1 = node, res2 = w;
    }

    cout << res1 << endl << (1ll * (sum - 1) * 2 - res2);

    return 0;
}


#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#define mp(a, b)    make_pair((a), (b))
#define pb          push_back

using namespace std;

int mmin=987654321, idx, n, m, u, v, degree[200000], isAttacked[200000], isUse[200000];
vector< vector<int> > node;
vector<int> vi;
map<int, int> cnt;

void dfs(int here) {
    isUse[here]=0;
    vi.pb(here);
    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(isUse[there]) {
            dfs(there);
            vi.pb(here);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=1 ; i<n ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].pb(v);
        node[v].pb(u);
        ++degree[u];
        ++degree[v];
        isUse[u]=isUse[v]=1;
    }

    for(int i=0 ; i<m ; ++i) {
        scanf("%d", &u);
        isAttacked[u]=1;
    }

    queue<int> q;
    for(int i=1 ; i<=n ; ++i) {
        if(degree[i]==1 && !isAttacked[i]) {
            q.push(i);
            isUse[i]=0;
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();

        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(isUse[there] && !isAttacked[there]) {
                --degree[there];
                if(degree[there]==0) {
                    isUse[there]=0;
                    q.push(there);
                }
            }
        }
    }

    int all=0;
    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) ++all;
    }

    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) {
            dfs(i);
            break;
        }
    }

    int last=vi.size();
    for(int i=1 ; i<last ; ++i)
        vi.pb(vi[i]);

    int lo=0;
    for(int i=0 ; i<vi.size() ; ++i) {
        int here=vi[i];
        ++cnt[here];

        while(lo<=i && (int)cnt.size()==all) {
            if(i-lo<mmin) {
                mmin=i-lo;
                idx=vi[lo];
            }
            else if(i-lo==mmin && vi[lo]<idx) idx=vi[lo];

            if(--cnt[vi[lo]]==0) cnt.erase(vi[lo]);
            ++lo;
        }
    }
    printf("%d\n%d\n", idx, mmin);
}


#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#define mp(a, b)    make_pair((a), (b))
#define pb          push_back

using namespace std;

int mmin=987654321, idx, n, m, u, v, degree[200000], isAttacked[200000], isUse[200000];
vector< vector<int> > node;
vector<int> vi;
map<int, int> cnt;

void dfs(int here) {
    isUse[here]=0;
    vi.pb(here);
    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(isUse[there]) {
            dfs(there);
            vi.pb(here);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=1 ; i<n ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].pb(v);
        node[v].pb(u);
        ++degree[u];
        ++degree[v];
        isUse[u]=isUse[v]=1;
    }

    for(int i=0 ; i<m ; ++i) {
        scanf("%d", &u);
        isAttacked[u]=1;
    }

    queue<int> q;
    for(int i=1 ; i<=n ; ++i) {
        if(degree[i]==1 && !isAttacked[i]) {
            q.push(i);
            isUse[i]=0;
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();

        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(isUse[there] && !isAttacked[there]) {
                --degree[there];
                if(degree[there]==0) {
                    isUse[there]=0;
                    q.push(there);
                }
            }
        }
    }

    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) {
            dfs(i);
            break;
        }
    }

    int last=vi.size();
    for(int i=1 ; i<last ; ++i)
        vi.pb(vi[i]);

    int lo=0;
    for(int i=0 ; i<vi.size() ; ++i) {
        int here=vi[i];
        if(isAttacked[here]) ++cnt[here];

        while(lo<=i && (int)cnt.size()==m) {
            if(i-lo<mmin) {
                mmin=i-lo;
                idx=vi[lo];
            }
            else if(i-lo==mmin && vi[lo]<idx) idx=vi[lo];
            if(isAttacked[vi[lo]] && --cnt[vi[lo]]==0) cnt.erase(vi[lo]);
            ++lo;
        }
    }
    printf("%d\n%d\n", idx, mmin);
}


#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#define mp(a, b)    make_pair((a), (b))
#define pb          push_back

using namespace std;

int mmin=987654321, idx, n, m, u, v, degree[200000], isAttacked[200000], isUse[200000];
vector< vector<int> > node;
vector<int> vi;
map<int, int> cnt;

void dfs(int here) {
    isUse[here]=0;
    vi.pb(here);
    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(isUse[there]) {
            dfs(there);
            vi.pb(here);
        }
    }
}

int main() {
    freopen("input.txt", "r", stdin);
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=1 ; i<n ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].pb(v);
        node[v].pb(u);
        ++degree[u];
        ++degree[v];
        isUse[u]=isUse[v]=1;
    }

    for(int i=0 ; i<m ; ++i) {
        scanf("%d", &u);
        isAttacked[u]=1;
    }

    queue<int> q;
    for(int i=1 ; i<=n ; ++i) {
        if(degree[i]==1 && !isAttacked[i]) {
            q.push(i);
            isUse[i]=0;
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();

        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(isUse[there] && !isAttacked[there]) {
                --degree[there];
                if(degree[there]==0) {
                    isUse[there]=0;
                    q.push(there);
                }
            }
        }
    }

    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) {
            dfs(i);
            break;
        }
    }

    int last=vi.size();
    for(int i=1 ; i<last ; ++i)
        vi.pb(vi[i]);

    int lo=0;
    for(int i=0 ; i<vi.size() ; ++i) {
        int here=vi[i];
        if(isAttacked[here]) ++cnt[here];

        while(lo<=i && lo<last && (int)cnt.size()==m) {
            if(i-lo<mmin) {
                mmin=i-lo;
                idx=vi[lo];
            }
            else if(i-lo==mmin && vi[lo]<idx) idx=vi[lo];

            if(isAttacked[vi[lo]] && --cnt[vi[lo]]==0) cnt.erase(vi[lo]);
            ++lo;
        }
        if(lo==last) break;
    }
    printf("%d\n%d\n", idx, mmin);
}


#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#define mp(a, b)    make_pair((a), (b))
#define pb          push_back

using namespace std;

int mmin=987654321, idx, n, m, u, v, degree[200000], isAttacked[200000], isUse[200000];
vector< vector<int> > node;
vector<int> vi;
map<int, int> cnt;

void dfs(int here) {
    isUse[here]=0;
    vi.pb(here);
    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(isUse[there]) {
            dfs(there);
            vi.pb(here);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=1 ; i<n ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].pb(v);
        node[v].pb(u);
        ++degree[u];
        ++degree[v];
        isUse[u]=isUse[v]=1;
    }

    for(int i=0 ; i<m ; ++i) {
        scanf("%d", &u);
        isAttacked[u]=1;
    }

    queue<int> q;
    for(int i=1 ; i<=n ; ++i) {
        if(degree[i]==1 && !isAttacked[i]) {
            q.push(i);
            isUse[i]=0;
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();

        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(isUse[there] && !isAttacked[there]) {
                --degree[there];
                if(degree[there]==0) {
                    isUse[there]=0;
                    q.push(there);
                }
            }
        }
    }

    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) {
            dfs(i);
            break;
        }
    }

    int last=vi.size();
    for(int i=1 ; i<last ; ++i)
        vi.pb(vi[i]);

    int lo=0;
    for(int i=0 ; i<vi.size() ; ++i) {
        int here=vi[i];
        if(isAttacked[here]) ++cnt[here];

        while(lo<=i && lo<last && (int)cnt.size()==m) {
            if(i-lo<mmin) {
                mmin=i-lo;
                idx=vi[lo];
            }
            else if(i-lo==mmin && vi[lo]<idx) idx=vi[lo];

            if(isAttacked[vi[lo]] && --cnt[vi[lo]]==0) cnt.erase(vi[lo]);
            ++lo;
        }
        if(lo==last) break;
    }
    printf("%d\n%d\n", idx, mmin);
}


#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#define mp(a, b)    make_pair((a), (b))
#define pb          push_back

using namespace std;

int mmin=987654321, idx, n, m, u, v, degree[200000], isAttacked[200000], isUse[200000];
vector< vector<int> > node;
vector<int> vi;
map<int, int> cnt;

void dfs(int here) {
    isUse[here]=0;
    vi.pb(here);
    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(isUse[there]) {
            dfs(there);
            vi.pb(here);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=1 ; i<n ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].pb(v);
        node[v].pb(u);
        ++degree[u];
        ++degree[v];
        isUse[u]=isUse[v]=1;
    }

    for(int i=0 ; i<m ; ++i) {
        scanf("%d", &u);
        isAttacked[u]=1;
    }

    queue<int> q;
    for(int i=1 ; i<=n ; ++i) {
        if(degree[i]==1 && !isAttacked[i]) {
            q.push(i);
            isUse[i]=0;
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();

        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(isUse[there] && !isAttacked[there]) {
                --degree[there];
                if(degree[there]==0) {
                    isUse[there]=0;
                    q.push(there);
                }
            }
        }
    }

    for(int i=1 ; i<=n ; ++i) {
        if(isUse[i]) {
            dfs(i);
            break;
        }
    }

    int last=vi.size();
    for(int i=1 ; i<last ; ++i)
        vi.pb(vi[i]);

    int lo=0;
    for(int i=0 ; i<vi.size() ; ++i) {
        int here=vi[i];
        if(isAttacked[here]) ++cnt[here];

        while(lo<=i && (int)cnt.size()==m) {
            if(i-lo<mmin) {
                mmin=i-lo;
                idx=vi[lo];
            }
            else if(i-lo==mmin && vi[lo]<idx) idx=vi[lo];

            if(isAttacked[vi[lo]] && --cnt[vi[lo]]==0) cnt.erase(vi[lo]);
            if(++lo==last) break;
        }
        if(lo==last) break;
    }
    printf("%d\n%d\n", idx, mmin);
}


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

using namespace std;

const int INF=987654331;
int n, m, u, v, idx=INF, mmax=0, D[200000];
bool A[200000], U[200000];
vector< vector<int> > node;

pair<int, int> dfs(int here) {
    U[here]=false;
    vector< pair<int, int> > child;

    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(U[there]) {
            pair<int, int> c=dfs(there);
            child.push_back(make_pair(c.first-1, c.second));
        }
    }

    if(child.empty()) return make_pair(0, here);
    sort(child.begin(), child.end());

    if(child.size()==1) {
        if(mmax<-child[0].first) {
            mmax=-child[0].first;
            idx=min(here, child[0].second);
        }
        else if(mmax==-child[0].first) idx=min(idx, min(here, child[0].second));
    }
    else {
        if(mmax<-(child[0].first+child[1].first)) {
            mmax=-(child[0].first+child[1].first);
            idx=min(child[0].second, child[1].second);
        }
        else if(mmax==-(child[0].first+child[1].first)) idx=min(idx, min(child[0].second, child[1].second));
    }
    return child[0];
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=0 ; i<n-1 ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].push_back(v);
        node[v].push_back(u);
        ++D[u]; ++D[v];
    }

    while(m--) {
        scanf("%d", &u);
        A[u]=true;
    }

    queue<int> q;
    memset(U, true, sizeof(U));
    for(int i=1 ; i<=n ; ++i) {
        if(!A[i] && D[i]==1) {
            U[i]=false;
            q.push(i);
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();
        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(U[there] && !A[there] && --D[there]==1) {
                U[there]=false;
                q.push(there);
            }
        }
    }

    int cnt=0;
    for(int i=1 ; i<=n ; ++i) {
        if(U[i]) {
            ++cnt;
            idx=i;
        }
    }
    for(int i=1 ; i<=n ; ++i) {
        if(U[i]) {
            dfs(i);
            break;
        }
    }
    --cnt;
    printf("%d\n%d\n", idx, cnt*2-mmax);
}


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

using namespace std;

const int INF=987654331;
int n, m, u, v, idx=INF, mmax=0, D[200000];
bool A[200000], U[200000];
vector< vector<int> > node;

pair<int, int> dfs(int here) {
    U[here]=false;
    vector< pair<int, int> > child;

    for(int i=0 ; i<node[here].size() ; ++i) {
        int there=node[here][i];
        if(U[there]) {
            pair<int, int> c=dfs(there);
            child.push_back(make_pair(c.first-1, c.second));
        }
    }

    if(child.empty()) return make_pair(0, here);
    sort(child.begin(), child.end());

    if(child.size()==1) {
        if(mmax<-child[0].first) {
            mmax=-child[0].first;
            idx=min(here, child[0].second);
        }
        else if(mmax==-child[0].first) idx=min(idx, min(here, child[0].second));
    }
    else {
        if(mmax<-(child[0].first+child[1].first)) {
            mmax=-(child[0].first+child[1].first);
            idx=min(child[0].second, child[1].second);
        }
        else if(mmax==-(child[0].first+child[1].first)) idx=min(idx, min(child[0].second, child[1].second));
    }
    return child[0];
}

int main() {
    scanf("%d%d", &n, &m);
    node.resize(n+1);
    for(int i=0 ; i<n-1 ; ++i) {
        scanf("%d%d", &u, &v);
        node[u].push_back(v);
        node[v].push_back(u);
        ++D[u]; ++D[v];
    }

    while(m--) {
        scanf("%d", &u);
        A[u]=true;
    }

    queue<int> q;
    memset(U, true, sizeof(U));
    for(int i=1 ; i<=n ; ++i) {
        if(!A[i] && D[i]==1) {
            U[i]=false;
            q.push(i);
        }
    }

    while(q.size()) {
        int here=q.front(); q.pop();
        for(int i=0 ; i<node[here].size() ; ++i) {
            int there=node[here][i];
            if(U[there] && !A[there] && --D[there]==1) {
                U[there]=false;
                q.push(there);
            }
        }
    }

    int cnt=0;
    for(int i=1 ; i<=n ; ++i) {
        if(U[i]) ++cnt;
    }
    for(int i=1 ; i<=n ; ++i) {
        if(U[i]) {
            dfs(i);
            break;
        }
    }
    --cnt;
    printf("%d\n%d\n", idx, cnt*2-mmax);
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
Lint localResult[MAX_N];

VI humans;
int firstRoot;
int nodes;

Lint bestResult;
int bestPosition;
Lint t;

int toKill;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void firstResultDfs(int v, int parent) {
    if (toKill) {
        bestResult = t;
    }
    if (attacked[v]) {
        --toKill;
    }
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                ++t;
                firstResultDfs(x, v);
                ++t;
            }
        }
    }
}

void improvingDfs(int v, int parent) {
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                localResult[x] = localResult[v] - (nodes - 2 * s[x]);
                if (localResult[x] < bestResult) {
                    bestPosition = x;
                    bestResult = localResult[x];
                } else if (localResult[x] == bestResult) {
                    if (x < bestPosition) {
                        bestPosition = x;
                        bestResult = localResult[x];
                    }
                }

                improvingDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    sort(humans.begin(), humans.end());

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    nodes = sizingDfs(firstRoot, -1);

    bestResult = 0;
    bestPosition = firstRoot;
    t = 0;
    toKill = m;
    firstResultDfs(firstRoot, -1);

    localResult[firstRoot] = bestResult;

//    improvingDfs(firstRoot, -1);

    cout << bestPosition + 1 << "\n" << bestResult;

    return 0;
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
Lint localResult[MAX_N];

VI humans;
int firstRoot;
int nodes;

Lint bestResult;
int bestPosition;
int t;

int toKill;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void firstResultDfs(int v, int parent) {
    if (toKill) {
        bestResult = t;
    }
    if (attacked[v]) {
        --toKill;
    }
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                ++t;
                firstResultDfs(x, v);
                ++t;
            }
        }
    }
}

void improvingDfs(int v, int parent) {
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                localResult[x] = min(localResult[x], localResult[v] - (nodes - 2 * s[x]));
                if (localResult[x] < bestResult) {
                    bestPosition = x;
                    bestResult = localResult[x];
                } else if (localResult[x] == bestResult) {
                    if (x < bestPosition) {
                        bestPosition = x;
                        bestResult = localResult[x];
                    }
                }

                improvingDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    nodes = sizingDfs(firstRoot, -1);

    bestResult = 0;
    bestPosition = firstRoot;
    t = 0;
    toKill = m;
    firstResultDfs(firstRoot, -1);

    REP(i, n) {
        localResult[i] = ((Lint) (1000000)) * (1000 * 1000);
    }
    localResult[firstRoot] = bestResult;

//    improvingDfs(firstRoot, -1);

    cout << bestPosition + 1 << "\n" << bestResult;

    return 0;
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
int dist[MAX_N];

VI humans;
int firstRoot;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void distDfs(int v, int parent) {
    if (parent == -1) {
        dist[v] = 0;
    } else {
        dist[v] = dist[parent] + 1;
    }

    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                distDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    sort(humans.begin(), humans.end());

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    sizingDfs(firstRoot, -1);

    distDfs(firstRoot, -1);

    int mostDistant = firstRoot;
    REP(i, n) {
        if (dist[i] > dist[mostDistant]) {
            mostDistant = i;
        }
    }

    distDfs(mostDistant, -1);
    int maxDist = 0;
    REP(i, n) {
        if (dist[i] > maxDist || (dist[i] == maxDist && i < mostDistant)) {
            mostDistant = i;
            maxDist = dist[i];
        }
    }

    cout << mostDistant + 1 << "\n" << 2 * s[firstRoot] - 2 - maxDist;

    return 0;
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
Lint localResult[MAX_N];

VI humans;
int firstRoot;
int nodes;

Lint bestResult;
int bestPosition;
Lint t;

int toKill;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void firstResultDfs(int v, int parent) {
    if (toKill) {
        bestResult = t;
    }
    if (attacked[v]) {
        --toKill;
    }
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                ++t;
                firstResultDfs(x, v);
                ++t;
            }
        }
    }
}

void improvingDfs(int v, int parent) {
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                localResult[x] = min(localResult[x], localResult[v] - (nodes - 2 * s[x]));
                if (localResult[x] < bestResult) {
                    bestPosition = x;
                    bestResult = localResult[x];
                } else if (localResult[x] == bestResult) {
                    if (x < bestPosition) {
                        bestPosition = x;
                        bestResult = localResult[x];
                    }
                }

                improvingDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    nodes = sizingDfs(firstRoot, -1);

    bestResult = 0;
    bestPosition = firstRoot;
    t = 0;
    toKill = m;
    firstResultDfs(firstRoot, -1);

    REP(i, n) {
        localResult[i] = ((Lint) (1000000)) * (1000 * 1000);
    }
    localResult[firstRoot] = bestResult;

    improvingDfs(firstRoot, -1);

    cout << bestPosition + 1 << "\n" << bestResult;

    return 0;
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
int dist[MAX_N];
int p[MAX_N];

VI humans;
int firstRoot;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void distDfs(int v, int parent) {
    p[v] = parent;

    if (parent == -1) {
        dist[v] = 0;
    } else {
        dist[v] = dist[parent] + 1;
    }

    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                distDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    sizingDfs(firstRoot, -1);

    distDfs(firstRoot, -1);

    int mostDistant = firstRoot;
    REP(i, n) {
        if ((dist[i] > dist[mostDistant]) || (dist[i] == dist[mostDistant] && i < mostDistant)) {
            mostDistant = i;
        }
    }

    distDfs(mostDistant, -1);
    int maxDist = 0;
    REP(i, n) {
        if (dist[i] > maxDist || (dist[i] == maxDist && i < mostDistant)) {
            mostDistant = i;
            maxDist = dist[i];
        }
    }

    int secondSide = mostDistant;
    int secondDistance = dist[secondSide];

    int center1 = secondSide;
    for (int i = 0; i < secondDistance / 2; ++i) {
        center1 = p[center1];
    }

    int center2 = p[center1];

    distDfs(center1, -1);
    int farthest = 0;
    REP(i, n) {
        if (dist[i] > dist[farthest] || (dist[i] == dist[farthest] && i < farthest)) {
            farthest = i;
        }
    }

    int farthest2 = 0;
    if (center2 != -1) {
        distDfs(center2, -1);
        REP(i, n) {
            if (dist[i] > dist[farthest2] || (dist[i] == dist[farthest2] && i < farthest2)) {
                farthest2 = i;
            }
        }
    }

    if (dist[farthest2] > dist[farthest] || (dist[farthest2] == dist[farthest] && farthest2 < farthest)) {
        farthest = farthest2;
    }

    distDfs(farthest, -1);
    int best = farthest;
    REP(i, n) {
        if (dist[i] > dist[best] || (dist[i] == dist[best] && i < best)) {
            best = i;
        }
    }

    cout << min(best, farthest) + 1 << "\n";
    cout << 2 * s[firstRoot] - 2 - maxDist;

    return 0;
}


// Author: Wojciech 'Ardavel' Szałapski
#define DEBUG 0

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef unsigned long long int uLint;
typedef long long int Lint;
typedef short int sint;
typedef long double ld;
typedef pair< int, int > PII;
typedef pair< PII, int > PPI;
typedef vector< int > VI;
typedef vector< ld > VD;
typedef vector< string > VS;
typedef vector< PII > VPII;
typedef vector< VI > VVI;
typedef queue< int > QI;
typedef queue< PII > QPII;

const int PRIME = 1000 * 1000 * 1000 + 7;
const int MULTIPLIER = 523;
const int INFI = (1 << 30) - 1;
const ld INF = 2 * 1e9 + 1;
const ld EPS = 1e-9;
const ld PI = 3.141592653589793238462643383279502884L;
const int DIM = 2;

#define X coord[0]
#define Y coord[1]

#define VAR(v, n) __typeof(n) v = (n)
#define REP(a, b) for(int a = 0;a < (b);++a)
#define FOR(a, b, c) for(int a = (b);a <= (c);++a)
#define FORD(a, b, c) for(int a = (b);a >= (c);--a)
#define FOREACH(it, s) for(VAR(it, (s).begin());it != (s).end();++it)
#define SIZE(x) (int)(x).size()
#define PB push_back
#define PF push_front
#define MP make_pair

const int MAX_N = 123456;

int n, m;

VI graph[MAX_N];
bool attacked[MAX_N];
bool cutoff[MAX_N];
int s[MAX_N];
int dist[MAX_N];

VI humans;
int firstRoot;

bool cuttingDfs(int v, int parent) {
    bool haveHumans = attacked[v];
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cuttingDfs(x, v)) {
                cutoff[x] = true;
            } else {
                haveHumans = true;
            }
        }
    }

    return haveHumans;
}

int sizingDfs(int v, int parent) {
    s[v] = 1;
    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                s[v] += sizingDfs(x, v);
            }
        }
    }

    return s[v];
}

void distDfs(int v, int parent) {
    if (parent == -1) {
        dist[v] = 0;
    } else {
        dist[v] = dist[parent] + 1;
    }

    REP(i, SIZE(graph[v])) {
        int x = graph[v][i];
        if (x != parent) {
            if (!cutoff[x]) {
                distDfs(x, v);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    REP(i, n - 1) {
        int a, b;
        cin >> a >> b;
        --a;
        --b;

        graph[a].PB(b);
        graph[b].PB(a);
    }

    REP(i, m) {
        int x;
        cin >> x;
        --x;
        humans.PB(x);

        attacked[x] = true;
    }

    firstRoot = humans[0];

    cuttingDfs(firstRoot, -1);

    sizingDfs(firstRoot, -1);

    distDfs(firstRoot, -1);

    int mostDistant = firstRoot;
    REP(i, n) {
        if ((dist[i] > dist[mostDistant]) || (dist[i] == dist[mostDistant] && i < mostDistant)) {
            mostDistant = i;
        }
    }

    distDfs(mostDistant, -1);
    int maxDist = 0;
    REP(i, n) {
        if (dist[i] > maxDist || (dist[i] == maxDist && i < mostDistant)) {
            mostDistant = i;
            maxDist = dist[i];
        }
    }

    cout << mostDistant + 1 << "\n" << 2 * s[firstRoot] - 2 - maxDist;

    return 0;
}