#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <functional>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#define nmax_def 110000
#define mod 1000000007
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
#define graph_from1 true
#define graph_tree true
#define graph_weight false
#define graph_digraph false

class Graph_func {
public:
	int Vnum;
	int Enum;
	int uini, vini;
	int xstop = -1;
	int decx = -1;
	int distuv;
	vector<pii> edgelist;
	vl edgeweight;
	vector<vi> adjlist;
	vector<vl> adjlistweight;
	vi adjnum;
	vi xprevlist;

	vl xdist;

	vb x_visited;
	vi x_prqarr;
	vb x_filled;

	void read_edge();
	void adjini();
	void visited_ini();
	void adjsort();
	vb graph_num_BFS(int BFS_ini, vb filled);
	int graph_num();
	void graph_BFS(ll BFS_ini);
	void graph_DFS(ll DFS_ini);
	void xydist_tree(int x);   // ex. xydist_tree(3)
	void xydist(int x);   // ex. xydist(3, 0)
	ll diameter();
	int dim_num(int dim);

	bool xydist_def = false;
};

void Graph_func::read_edge() {
	cin >> Vnum >> uini >> vini;
	if (graph_tree)
		Enum = Vnum - 1;// graph
	else
		cin >> Enum;
	uini--;
	vini--;
	edgelist.resize(Enum);
	edgeweight.resize(Enum);
	adjnum.resize(Vnum);
	xdist.resize(Vnum);
	adjlist.resize(Vnum);
	xprevlist.resize(Vnum);
	if (graph_weight)
		adjlistweight.resize(Vnum);
	rep(i, Enum) {
		if (graph_weight)
			cin >> edgelist[i].first >> edgelist[i].second >> edgeweight[i];
		else
			cin >> edgelist[i].first >> edgelist[i].second;
		if (graph_from1) {
			edgelist[i].first--;
			edgelist[i].second--;
		}
	}
	return;
}

void Graph_func::adjini() {
	rep(i, Vnum)
		adjnum[i] = 0;
	rep(i, Enum) {
		int x = edgelist[i].first;
		int y = edgelist[i].second;
		adjlist[x].push_back(y);
		if (!graph_digraph)
			adjlist[y].push_back(x);
		if (graph_weight) {
			ll xyweight = edgeweight[i];
			adjlistweight[x].push_back(xyweight);
			if (!graph_digraph)
				adjlistweight[y].push_back(xyweight);
		}
		adjnum[x]++;
		if (!graph_digraph)
			adjnum[y]++;
	}
	x_visited.resize(Vnum);
	visited_ini();

	return;
}

void Graph_func::visited_ini() {
	rep(i, Vnum) {
		xdist[i] = -1;
		x_visited[i] = false;
	}
	x_prqarr.resize(0);
}

void Graph_func::graph_BFS(ll BFS_ini) {
	visited_ini();
	x_prqarr.push_back(BFS_ini);
	x_visited[BFS_ini] = true;

	while (!x_prqarr.empty()) {
		int Ntmp = x_prqarr.size();
		rep(a, Ntmp) {
			int x = x_prqarr[0];
			x_prqarr.erase(x_prqarr.begin());
			rep(i, adjnum[x]) {
				int x_new = adjlist[x][i];
				if (!x_visited[x_new]) {
					xprevlist[x_new] = x;
					x_prqarr.push_back(x_new);
					x_visited[x_new] = true;
				}
			}
		}
	}
	return;
}

void Graph_func::graph_DFS(ll DFS_ini) {
	visited_ini();
	x_prqarr.push_back(DFS_ini);
	x_visited[DFS_ini] = true;

	while (!x_prqarr.empty()) {
		int Ntmp = x_prqarr.size();
		rep(a, Ntmp) {
			int x = x_prqarr[x_prqarr.size() - 1];
			x_prqarr.pop_back();
			rep(i, adjnum[x]) {
				int x_new = adjlist[x][i];
				if (!x_visited[x_new]) {
					x_prqarr.push_back(x_new);
					x_visited[x_new] = true;
				}
			}
		}
	}
	return;
}

void Graph_func::xydist_tree(int BFS_ini) {  // ex. xydist_tree(3), BFS
	visited_ini();
	x_prqarr.push_back(BFS_ini);
	x_visited[BFS_ini] = true;

	while (!x_prqarr.empty()) {
		int Ntmp = x_prqarr.size();
		rep(a, Ntmp) {
			int x = x_prqarr[0];
			x_prqarr.erase(x_prqarr.begin());
			rep(i, adjnum[x]) {
				int x_new = adjlist[x][i];
				if (x_new == xstop)
					continue;
				int dist_new;
				if (graph_weight)
					dist_new = adjlistweight[x][i];
				else
					dist_new = 1;
				if (!x_visited[x_new]) {
					x_prqarr.push_back(x_new);
					xdist[x_new] = xdist[x] + dist_new;
					x_visited[x_new] = true;
					//cout << x_new << endl;
				}
			}
		}
	}
	return;
}

int main(void) {
	Graph_func graph;
	ll ans = 0;
	graph.read_edge();
	graph.adjini();
	ll Vnum = graph.Vnum;
	ll Enum = graph.Enum;
	graph.graph_BFS(graph.uini);
	ll distuv = 0;
	int xtmp = graph.vini;
	vi waylist(1);
	waylist[0] = xtmp;
	while (1) {
		xtmp = graph.xprevlist[xtmp];
		distuv++;
		waylist.push_back(xtmp);
		if (xtmp == graph.uini)
			break;
	}
	vl anslist(Vnum, 0);
	graph.decx = waylist[distuv - 1];
	graph.distuv = distuv;
	graph.visited_ini();
	graph.xydist_tree(graph.uini);
	rep(i, Vnum) {
		anslist[i] = graph.xdist[i];
	}
	graph.visited_ini();
	graph.xydist_tree(graph.vini);
	rep(i, Vnum) {
		if (anslist[i] < graph.xdist[i])
			anslist[i] = graph.xdist[i];
		else
			anslist[i] = 0;
	}
	rep(i, Vnum) {
		ans = max(anslist[i], ans);
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 10488