#include <bits/stdc++.h>
const int N = 1e5;
struct Edge {
  int to, nxt, w;
} e[N * 2 + 10];
int head[N + 10], tote = 1;
inline void addEdge(int u, int v, int w) {
  e[++tote].to = v;
  e[tote].w = w;
  e[tote].nxt = head[u];
  head[u] = tote;
}
struct Node {
  int u, dis;
  Node(int _u = 0, int _dis = 0) : u(_u), dis(_dis) {}
  inline bool operator<(const Node& rhs) const { return dis > rhs.dis; }
};
int n, dfn[N + 10], stk[N + 10], top, low[N + 10], inStk[N + 10], cnt,
    ring[N + 10], totr;
int dis[N + 10], vis[N + 10];
bool DFS(int u, int _fa) {
  dfn[u] = low[u] = ++cnt;
  stk[++top] = u, inStk[u] = 1;
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (i == (_fa ^ 1)) continue;
    if (!dfn[v]) {
      if (DFS(v, i)) return 1;
      low[u] = std::min(low[u], low[v]);
    } else if (inStk[v])
      low[u] = std::min(low[u], dfn[v]);
  }
  if (dfn[u] == low[u]) {
    int v;
    do v = stk[top--], inStk[v] = 0, ring[++totr] = v;
    while (u != v);
    if (totr >= 2) return 1;
    totr = 0;
  }
  return 0;
}
void Dijkstra(int s) {
  std::priority_queue<Node> q;
  q.push(s);
  memset(dis, 0x3f, sizeof(dis));
  dis[s] = 0;
  while (!q.empty()) {
    int u = q.top().u;
    q.pop();
    if (vis[u]) continue;
    vis[u] = 1;
    for (int i = head[u]; i; i = e[i].nxt) {
      int v = e[i].to;
      if (dis[v] > dis[u] + e[i].w) {
        dis[v] = dis[u] + e[i].w;
        q.push(Node(v, dis[v]));
      }
    }
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    addEdge(u, v, 1);
    addEdge(v, u, 1);
  }
  for (int i = 1; i <= n; i++)
    if (DFS(i, 0)) break;
  for (int i = 1; i <= totr; i++) {
    addEdge(n + 1, ring[i], 0);
    addEdge(ring[i], n + 1, 0);
  }
  Dijkstra(n + 1);
  for (int i = 1; i <= n; i++) printf("%d%c", dis[i], " \n"[i == n]);
  return 0;
}
