#include using namespace std; #define FOR(a, b, c) for(int a = b; a < c; a++) const int N = 2e5+7; vector graf[N]; int dist[N]; int order[N]; int revorder[N]; int rootdist[N]; int n, m; struct LCA { vector tree[N]; int nr[N], pre[N], fir[N]; int TIME = 0, id = 0; int sparse[2 * N][21]; void dfs(int u, int p = -1) { pre[u] = TIME; nr[TIME] = u; sparse[id][0] = TIME++; fir[u] = id++; for (auto& v : tree[u]) if (v != p) { rootdist[v] = rootdist[u] + 1; dfs(v, u); sparse[id++][0] = pre[u]; } } void calc() { dfs(0); for (int j = 1; (1 << j) <= id; j++) for (int i = 0; i + (1 << j) -1 < id; ++i) { sparse[i][j] = min(sparse[i][j - 1], sparse[i + (1 << (j - 1))][j - 1]); } } int minq(int l, int r) { int k = 31 - __builtin_clz(r - l + 1); return min(sparse[l][k], sparse[r - (1 << k) + 1][k]); } int query(int a, int b) { a = fir[a], b = fir[b]; if (a > b) swap(a, b); return nr[minq(a, b)]; } void addEdge(int a, int b) { tree[a].push_back(b); tree[b].push_back(a); } }; LCA lca; void bfs(int s) { dist[s] = 1; queue q; q.push(s); while(q.size()) { auto v = q.front(); q.pop(); for (auto& u : graf[v]) { if (!dist[u]) { dist[u] = dist[v] + 1; q.push(u); } } } } void generate_tree() { vector > temp(n); for (int i = 0; i < n; ++i) { temp[i] = {dist[i], i}; } sort(temp.begin(), temp.end()); for (int i = 0; i < n; ++i) { order[i] = temp[i].second; revorder[temp[i].second] = order[i]; } for (int i = 1; i < n; ++i) { int v = order[i]; int minn = n; for (auto& u : graf[v]) { minn = min(minn, revorder[u]); } lca.addEdge(i, minn); } } void calcRes() { lca.calc(); long long res = 0; for (int i = 1; i < n; ++i) { res += rootdist[i - 1] + rootdist[i] - 2 * rootdist[lca.query(i - 1, i)]; } cout << res << "\n"; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m; for (int i = 0; i < m; ++i) { int a, b; cin >> a >> b; graf[a].push_back(b); graf[b].push_back(a); } bfs(0); generate_tree(); calcRes(); }