#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int ret = 0;
  char ch = getchar();
  while (ch < '0' || ch > '9') ch = getchar();
  do {
    ret = ret * 10 + ch - '0';
    ch = getchar();
  } while ('0' <= ch && ch <= '9');
  return ret;
}
inline void write(int x) {
  if (!x) return;
  write(x / 10);
  putchar(x % 10 + '0');
}
int n;
struct node {
  int v;
  node *nxt;
} e[2 * 200100], *h[200100];
int z;
inline void addedge(int u, int v) {
  e[++z].v = v;
  e[z].nxt = h[u];
  h[u] = &e[z];
  e[++z].v = u;
  e[z].nxt = h[v];
  h[v] = &e[z];
}
struct data {
  pair<int, int> p1, p2;
  void update(pair<int, int> x) {
    if (x > p1) {
      p2 = p1;
      p1 = x;
    } else if (x > p2)
      p2 = x;
  }
  bool operator<(data p) const {
    return p1.first != p.p1.first ? p1.first < p.p1.first
                                  : p2.first < p.p2.first;
  }
} pool[200100];
int dep[200100];
pair<int, int> md[200100];
void dfs(int x, int fa) {
  md[x] = pair<int, int>(1, x);
  for (node *p = h[x]; p; p = p->nxt)
    if (p->v != fa) {
      dep[p->v] = dep[x] + 1;
      dfs(p->v, x);
      md[x] = max(md[x], pair<int, int>(md[p->v].first + 1, md[p->v].second));
      pool[x].update(md[p->v]);
    }
}
int root = 1;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n;
  for (int i = 0, u, v; i < n - 1; i++) {
    cin >> u >> v;
    addedge(u, v);
  }
  dfs(1, 0);
  for (int i = 2; i <= n; i++)
    if (pool[i].p2.second &&
        (dep[root] < dep[i] || dep[root] == dep[i] && pool[root] < pool[i]))
      root = i;
  int x = pool[root].p1.second, y = pool[root].p2.second;
  memset(pool, 0, sizeof pool);
  dep[root] = 0;
  dfs(root, 0);
  for (int i = 1; i <= n; i++)
    if (pool[i].p2.second &&
        (dep[root] < dep[i] || dep[root] == dep[i] && pool[root] < pool[i]))
      root = i;
  cout << x << ' ' << pool[root].p1.second << '\n'
       << y << ' ' << pool[root].p2.second << endl;
  return 0;
}
