题目大意
给定一个
n
n
n 个点
m
m
m 条边的无向图,找到两个点
s
,
t
s,t
s,t,使得
s
s
s 到
t
t
t 必须 经过的边最多(一条边无论走哪条路线都经过 ta
,这条边就是必须经过的边)。
对于 100 % 100\% 100% 的数据, 2 < = n < = 3 ∗ 1 0 5 , 1 < = m < = 3 ∗ 1 0 5 2<=n<=3*10^5,1<=m<=3*10^5 2<=n<=3∗105,1<=m<=3∗105。
解题思路
首先,我们知道同一个 边双连通分量 中,任意两点之间存在至少两条无重边的简单路径。
我们可以发现同一个边双内的点之间没有必须经过的边。
所以将边双缩成一个点,不影响题意。
缩完之后,因为没有环,说明是一棵树,树边都是必须经过的边。
那么当前这棵树的直径即是答案。
具体见代码。
CODE
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
inline void write(int x)
{
if(x < 0)
{
putchar('-');
x = -x;
}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int _ = 3 * 1e5 + 7;
int n, m;
struct Grath
{
int tot, head[_], to[_ << 1], nxt[_ << 1];
void add(int u, int v)
{
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
} e1, e2;
int cnt_node, cntn, dfn[_], low[_], id[_], vis[_ << 1];
stack<int> s;
int u[_], v[_];
int p, mmax, dis[_];
int js(int x)
{
return (x % 2) ? x + 1 : x - 1;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++cnt_node;
s.push(u);
for(int i = e1.head[u]; i; i = e1.nxt[i])
if(!vis[i])
{
int v = e1.to[i];
vis[i] = vis[js(i)] = 1;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u])
{
cntn++;
while(1)
{
int now = s.top();
s.pop();
id[now] = cntn;
if(now == u) break;
}
}
}
void dfs(int u, int fa)
{
for(int i = e2.head[u]; i; i = e2.nxt[i])
{
int v = e2.to[i];
if(v == fa) continue;
dis[v] = dis[u] + 1;
dfs(v, u);
}
}
signed main()
{
n = read(), m = read();
for(int i = 1; i <= m; ++i)
{
u[i] = read(), v[i] = read();
e1.add(u[i], v[i]);
e1.add(v[i], u[i]);
}
for(int i = 1; i <= n; ++i)
if(!dfn[i]) tarjan(i);
for(int i = 1; i <= m; ++i)
{
if(id[u[i]] != id[v[i]])
{
e2.add(id[u[i]], id[v[i]]);
e2.add(id[v[i]], id[u[i]]);
}
}
dfs(1, 0);
for(int i = 1; i <= cntn; ++i)
{
if(dis[i] > mmax)
{
mmax = dis[i];
p = i;
}
dis[i] = 0;
}
dfs(p, 0);
mmax = 0;
for(int i = 1; i <= cntn; ++i)
mmax = max(mmax, dis[i]);
write(mmax);
putchar('\n');
return 0;
}