import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import core.thread;
import std.typecons;

void test () {
  int n, a, b;
  readf (" %d %d %d", &n, &a, &b);
  --a; --b;
  auto e = new int[][n];
  foreach (i; 1 .. n) {
    int x, y;
    readf (" %d %d", &x, &y);
    --x; --y;
    e[x] ~= y;
    e[y] ~= x;
  }
  auto u = new int[n];
  auto v = new int[n];
  auto parent = new int[n];
  int curt = 0;
  void go (int i) {
    u[i] = ++curt;
    foreach (j; e[i]) {
      if (parent[j]==-2) {
        parent[j] = i;
        go (j);
      }
    }
    v[i] = ++curt;
  }
  parent[] = -2;
  parent[0] = -1;
  go (0);
  bool isAncestor (int parent, int child) {
    return (u[parent] <= u[child] && v[child] <= v[parent]);
  }
  int aokiMove (int t, int a) {
    debug stderr.writefln ("%d: (%d, %d)", t, u[t], v[t]);
    debug stderr.writefln ("%d: (%d, %d)", a, u[a], v[a]);
    if (t == a) return -1;
    if (isAncestor (t, a)) return parent[a];
    foreach (j; e[a]) {
      debug stderr.writefln ("%d: (%d, %d)", j, u[j], v[j]);
      if (isAncestor (j, t)) return j;
    }
    return parent[a];
    assert (0, format ("t = %d, a = %d", t, a));
  }
  Tuple!(int,int)[] q;
  q ~= tuple (a, b);
  auto vis = new bool[n];
  vis[a] = true;
  int left = 0;
  auto d = new int[n];
  while (left < q.length) {
    auto w = q[left++];
    if (w[0] == w[1]) continue;
    foreach (j; e[w[0]]) {
      if (j != w[1] && !vis[j]) {
        vis[j] = true;
        int o = aokiMove (j, w[1]); 
        d[j] = d[w[0]];
        ++d[j];
        q ~= tuple (j, o);
      }
    }
  }
  int res;
  foreach (i; d) res = max (res, i);
  writeln (res);
}

void main() {
  auto t = new Thread (&test, 64 << 20);
  t.start ();
  t.join ();
}

