#include <stdio.h>
#include <vector>
#include <queue>
#include <memory.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 500000;
int n, m;
int L[N], Z[N], maxLen[N];
vector<vector<pair<int, int> > > g;
bool isBridge[2 * N];
int low[N], idx[N], dfs;
bool vis[N];
int parent[N];
void markBridges(int u, int p) {
low[u] = idx[u] = ++dfs;
for (int i = 0; i < g[u].size(); ++i) {
int v = g[u][i].first;
if (idx[v] == 0) {
markBridges(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > idx[u])
isBridge[g[u][i].second] = true;
}
else if (v != p)
low[u] = min(low[u], idx[v]);
}
}
void findASpanningTreeAndInitializeL(int startingNode) {
queue<int> q;
vector<int> nodesByDepth;
q.push(startingNode);
memset(vis, 0, sizeof(vis));
vis[startingNode] = true;
parent[startingNode] = -1;
while (!q.empty()) {
int u = q.front();
q.pop();
nodesByDepth.push_back(u);
for (auto e : g[u]) {
int v = e.first;
if (vis[v])
continue;
vis[v] = true;
parent[v] = u;
q.push(v);
}
}
for (int i = n - 1; i >= 0; --i) {
int u = nodesByDepth[i];
for (auto e : g[u]) {
int v = e.first;
if (parent[v] == u) {
maxLen[u] = max(maxLen[u], 1 + maxLen[v]);
if (isBridge[e.second])
L[u] = max(L[u], 1 + maxLen[v]);
}
}
}
}
vector<vector<int> > cycles; // actually components after removing bridges, not cycles (as there can be a single node).
int cycleIdx[N];
void findCycles(int u) {
vis[u] = true;
cycles.back().push_back(u);
cycleIdx[u] = cycles.size() - 1;
for (auto e : g[u])
if (!isBridge[e.second] && !vis[e.first])
findCycles(e.first);
}
void solveCycles(int u, int p, int upValue) {
L[u] = max(L[u], upValue);
vector<int> &cycle = cycles[cycleIdx[u]];
int k = cycle.size();
for (int it = 0; it < 2; ++it) { // two iterations, clockwise and counter clockwise
priority_queue<pair<int, int> > q;
for (int i = 0; i < 2 * k; ++i) {
int d = 2 * k - i;
while (!q.empty() && q.top().second - d > k / 2)
q.pop();
if (!q.empty())
Z[cycle[i%k]] = max(Z[cycle[i%k]], q.top().first - d);
q.push({ L[cycle[i%k]] + d,d });
}
reverse(cycle.begin(), cycle.end());
}
for (auto u : cycle) {
int firstMax = 0, secondMax = 0;
for (auto e : g[u])
if (e.first != p && isBridge[e.second]) {
int v = e.first;
if (secondMax < 1 + maxLen[v]) {
secondMax = 1 + maxLen[v];
if (firstMax < secondMax)
swap(firstMax, secondMax);
}
}
for (auto e : g[u])
if (e.first != p && isBridge[e.second]) {
int v = e.first;
int passValue = max(upValue, Z[u]);
if (firstMax == 1 + maxLen[v])
passValue = max(passValue, secondMax);
else
passValue = max(passValue, firstMax);
solveCycles(v, u, passValue + 1);
}
}
}
int main()
{
scanf("%d%d", &n, &m);
g.resize(n);
for (int i = 0, u, v; i < m; ++i) {
scanf("%d%d", &u, &v);
--u; --v;
g[u].push_back({ v,i });
g[v].push_back({ u,i });
}
markBridges(0, -1);
for (int i = 0; i < n; ++i)
if (!vis[i]) {
cycles.push_back(vector<int>());
findCycles(i);
}
findASpanningTreeAndInitializeL(0);
solveCycles(0, -1, 0);
for (int i = 0; i < n; ++i) {
if (i > 0)
printf(" ");
printf("%d", max(L[i], Z[i]));
}
printf("\n");
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPG1lbW9yeS5oPgojaW5jbHVkZSA8YWxnb3JpdGhtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwp0eXBlZGVmIGxvbmcgbG9uZyBsbDsKY29uc3QgaW50IE4gPSA1MDAwMDA7CmludCBuLCBtOwppbnQgTFtOXSwgWltOXSwgbWF4TGVuW05dOwp2ZWN0b3I8dmVjdG9yPHBhaXI8aW50LCBpbnQ+ID4gPiBnOwpib29sIGlzQnJpZGdlWzIgKiBOXTsKaW50IGxvd1tOXSwgaWR4W05dLCBkZnM7CmJvb2wgdmlzW05dOwppbnQgcGFyZW50W05dOwp2b2lkIG1hcmtCcmlkZ2VzKGludCB1LCBpbnQgcCkgewoJbG93W3VdID0gaWR4W3VdID0gKytkZnM7Cglmb3IgKGludCBpID0gMDsgaSA8IGdbdV0uc2l6ZSgpOyArK2kpIHsKCQlpbnQgdiA9IGdbdV1baV0uZmlyc3Q7CgkJaWYgKGlkeFt2XSA9PSAwKSB7CgkJCW1hcmtCcmlkZ2VzKHYsIHUpOwoJCQlsb3dbdV0gPSBtaW4obG93W3VdLCBsb3dbdl0pOwoJCQlpZiAobG93W3ZdID4gaWR4W3VdKQoJCQkJaXNCcmlkZ2VbZ1t1XVtpXS5zZWNvbmRdID0gdHJ1ZTsKCQl9CgkJZWxzZSBpZiAodiAhPSBwKQoJCQlsb3dbdV0gPSBtaW4obG93W3VdLCBpZHhbdl0pOwoJfQp9CnZvaWQgZmluZEFTcGFubmluZ1RyZWVBbmRJbml0aWFsaXplTChpbnQgc3RhcnRpbmdOb2RlKSB7CglxdWV1ZTxpbnQ+IHE7Cgl2ZWN0b3I8aW50PiBub2Rlc0J5RGVwdGg7CglxLnB1c2goc3RhcnRpbmdOb2RlKTsKCW1lbXNldCh2aXMsIDAsIHNpemVvZih2aXMpKTsKCXZpc1tzdGFydGluZ05vZGVdID0gdHJ1ZTsKCXBhcmVudFtzdGFydGluZ05vZGVdID0gLTE7Cgl3aGlsZSAoIXEuZW1wdHkoKSkgewoJCWludCB1ID0gcS5mcm9udCgpOwoJCXEucG9wKCk7CgkJbm9kZXNCeURlcHRoLnB1c2hfYmFjayh1KTsKCQlmb3IgKGF1dG8gZSA6IGdbdV0pIHsKCQkJaW50IHYgPSBlLmZpcnN0OwoJCQlpZiAodmlzW3ZdKQoJCQkJY29udGludWU7CgkJCXZpc1t2XSA9IHRydWU7CgkJCXBhcmVudFt2XSA9IHU7CgkJCXEucHVzaCh2KTsKCQl9Cgl9Cglmb3IgKGludCBpID0gbiAtIDE7IGkgPj0gMDsgLS1pKSB7CgkJaW50IHUgPSBub2Rlc0J5RGVwdGhbaV07CgkJZm9yIChhdXRvIGUgOiBnW3VdKSB7CgkJCWludCB2ID0gZS5maXJzdDsKCQkJaWYgKHBhcmVudFt2XSA9PSB1KSB7CgkJCQltYXhMZW5bdV0gPSBtYXgobWF4TGVuW3VdLCAxICsgbWF4TGVuW3ZdKTsKCQkJCWlmIChpc0JyaWRnZVtlLnNlY29uZF0pCgkJCQkJTFt1XSA9IG1heChMW3VdLCAxICsgbWF4TGVuW3ZdKTsKCQkJfQoJCX0KCX0KfQp2ZWN0b3I8dmVjdG9yPGludD4gPiBjeWNsZXM7IC8vIGFjdHVhbGx5IGNvbXBvbmVudHMgYWZ0ZXIgcmVtb3ZpbmcgYnJpZGdlcywgbm90IGN5Y2xlcyAoYXMgdGhlcmUgY2FuIGJlIGEgc2luZ2xlIG5vZGUpLgppbnQgY3ljbGVJZHhbTl07CnZvaWQgZmluZEN5Y2xlcyhpbnQgdSkgewoJdmlzW3VdID0gdHJ1ZTsKCWN5Y2xlcy5iYWNrKCkucHVzaF9iYWNrKHUpOwoJY3ljbGVJZHhbdV0gPSBjeWNsZXMuc2l6ZSgpIC0gMTsKCWZvciAoYXV0byBlIDogZ1t1XSkKCQlpZiAoIWlzQnJpZGdlW2Uuc2Vjb25kXSAmJiAhdmlzW2UuZmlyc3RdKQoJCQlmaW5kQ3ljbGVzKGUuZmlyc3QpOwp9CnZvaWQgc29sdmVDeWNsZXMoaW50IHUsIGludCBwLCBpbnQgdXBWYWx1ZSkgewoJTFt1XSA9IG1heChMW3VdLCB1cFZhbHVlKTsKCXZlY3RvcjxpbnQ+ICZjeWNsZSA9IGN5Y2xlc1tjeWNsZUlkeFt1XV07CglpbnQgayA9IGN5Y2xlLnNpemUoKTsKCWZvciAoaW50IGl0ID0gMDsgaXQgPCAyOyArK2l0KSB7IC8vIHR3byBpdGVyYXRpb25zLCBjbG9ja3dpc2UgYW5kIGNvdW50ZXIgY2xvY2t3aXNlCgkJcHJpb3JpdHlfcXVldWU8cGFpcjxpbnQsIGludD4gPiBxOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgMiAqIGs7ICsraSkgewoJCQlpbnQgZCA9IDIgKiBrIC0gaTsKCQkJd2hpbGUgKCFxLmVtcHR5KCkgJiYgcS50b3AoKS5zZWNvbmQgLSBkID4gayAvIDIpCgkJCQlxLnBvcCgpOwoJCQlpZiAoIXEuZW1wdHkoKSkKCQkJCVpbY3ljbGVbaSVrXV0gPSBtYXgoWltjeWNsZVtpJWtdXSwgcS50b3AoKS5maXJzdCAtIGQpOwoJCQlxLnB1c2goeyBMW2N5Y2xlW2kla11dICsgZCxkIH0pOwoJCX0KCQlyZXZlcnNlKGN5Y2xlLmJlZ2luKCksIGN5Y2xlLmVuZCgpKTsKCX0KCWZvciAoYXV0byB1IDogY3ljbGUpIHsKCQlpbnQgZmlyc3RNYXggPSAwLCBzZWNvbmRNYXggPSAwOwoJCWZvciAoYXV0byBlIDogZ1t1XSkKCQkJaWYgKGUuZmlyc3QgIT0gcCAmJiBpc0JyaWRnZVtlLnNlY29uZF0pIHsKCQkJCWludCB2ID0gZS5maXJzdDsKCQkJCWlmIChzZWNvbmRNYXggPCAxICsgbWF4TGVuW3ZdKSB7CgkJCQkJc2Vjb25kTWF4ID0gMSArIG1heExlblt2XTsKCQkJCQlpZiAoZmlyc3RNYXggPCBzZWNvbmRNYXgpCgkJCQkJCXN3YXAoZmlyc3RNYXgsIHNlY29uZE1heCk7CgkJCQl9CgkJCX0KCQlmb3IgKGF1dG8gZSA6IGdbdV0pCgkJCWlmIChlLmZpcnN0ICE9IHAgJiYgaXNCcmlkZ2VbZS5zZWNvbmRdKSB7CgkJCQlpbnQgdiA9IGUuZmlyc3Q7CgkJCQlpbnQgcGFzc1ZhbHVlID0gbWF4KHVwVmFsdWUsIFpbdV0pOwoJCQkJaWYgKGZpcnN0TWF4ID09IDEgKyBtYXhMZW5bdl0pCgkJCQkJcGFzc1ZhbHVlID0gbWF4KHBhc3NWYWx1ZSwgc2Vjb25kTWF4KTsKCQkJCWVsc2UKCQkJCQlwYXNzVmFsdWUgPSBtYXgocGFzc1ZhbHVlLCBmaXJzdE1heCk7CgkJCQlzb2x2ZUN5Y2xlcyh2LCB1LCBwYXNzVmFsdWUgKyAxKTsKCQkJfQoJfQp9CmludCBtYWluKCkKewoJc2NhbmYoIiVkJWQiLCAmbiwgJm0pOwoJZy5yZXNpemUobik7Cglmb3IgKGludCBpID0gMCwgdSwgdjsgaSA8IG07ICsraSkgewoJCXNjYW5mKCIlZCVkIiwgJnUsICZ2KTsKCQktLXU7IC0tdjsKCQlnW3VdLnB1c2hfYmFjayh7IHYsaSB9KTsKCQlnW3ZdLnB1c2hfYmFjayh7IHUsaSB9KTsKCX0KCW1hcmtCcmlkZ2VzKDAsIC0xKTsKCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKQoJCWlmICghdmlzW2ldKSB7CgkJCWN5Y2xlcy5wdXNoX2JhY2sodmVjdG9yPGludD4oKSk7CgkJCWZpbmRDeWNsZXMoaSk7CgkJfQoJZmluZEFTcGFubmluZ1RyZWVBbmRJbml0aWFsaXplTCgwKTsKCXNvbHZlQ3ljbGVzKDAsIC0xLCAwKTsKCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKSB7CgkJaWYgKGkgPiAwKQoJCQlwcmludGYoIiAiKTsKCQlwcmludGYoIiVkIiwgbWF4KExbaV0sIFpbaV0pKTsKCX0KCXByaW50ZigiXG4iKTsKCXJldHVybiAwOwp9