CF1000E We Need More Bosses [缩点,直径]
根据强连通分量的性质,对于 \(u,v\in V\),\(u\) 可以到达 \(v\),\(v\) 可以到达 \(u\)。
显然同一个强连通分量的不是必经边,所以缩完搞个直径就完事了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct io {
char buf[1 << 26 | 3], *s; int f;
io() { f = 0, buf[fread(s = buf, 1, 1 << 26, stdin)] = '\n'; }
io& operator >> (int&x) {
for(x = f = 0; !isdigit(*s); ++s) f |= *s == '-';
while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
return x = f ? -x : x, *this;
}
};
int n, m;
const int maxn = 3e5 + 53;
struct edge {
int v, nxt;
} e[maxn << 1];
int head[maxn], cnt = 0;
void add(int u, int v) { e[++ cnt] = { v , head[u] } , head[u] = cnt; }
int st[maxn], top = 0;
int dfn[maxn], low[maxn], idx = 0;
int col[maxn], c = 0;
void tarjan(int u, int f) {
dfn[u] = ++ idx, low[u] = dfn[u];
st[++ top] = u;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if(v == f) continue;
if(!dfn[v]) tarjan(v, u), low[u] = min(low[u], low[v]);
else if(!col[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]) {
++c;
while(st[top + 1] ^ u) { col[st[top --]] = c; }
}
}
vector <int> g[maxn];
int dep[maxn];
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
for(int v : g[u]) {
if(v ^ fa)
dfs(v, u);
}
}
#define out cout
signed main() {
#ifdef LOCAL
#define in cin
ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
freopen("testdata.in", "r", stdin);
#else
io in;
#endif
in >> n >> m;
vector<pair<int, int>> E;
for(int i = 0 ; i < m ; i ++) {
int u, v; in >> u >> v;
add(u, v), add(v, u);
E.push_back({u, v});
}
for(int i = 1 ; i <= n ; i ++) {
if(! dfn[i]) tarjan(i, 0);
}
for(auto x : E) {
int u = x.first, v = x.second;
if(col[u] ^ col[v]) {
g[col[u]].push_back(col[v]);
g[col[v]].push_back(col[u]);
}
}
int rt;
rt = 1;
dfs(rt, 0);
int mx = 1;
for(int i = 1 ; i <= n ; i ++) if(dep[mx] < dep[i]) mx = i;
rt = mx;
dfs(rt, 0); mx = 0;
for(int i = 1 ; i <= n ; i ++) mx = max(dep[i], mx);
out << mx - 1 << '\n';
return 0;
}