Description
给定一个 (n) 个点 (m) 条边的无向图,找到两个点 (s,t),使得 (s) 到 (t) 必须经过的边最多。
Solution
边双内的边显然都不是关键边,否则必是,于是缩点后求直径即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
struct Edge
{
int from,next,to;
} e[N];
vector <int> g[N];
int n,m,t1,t2,dfn[N],low[N],head[N],bridge[N],bel[N],tot=1,ind,cnt;
void __addedge(int u,int v)
{
e[++tot].next=head[u];
e[tot].to=v;
head[u]=tot;
}
void addedge(int u,int v)
{
__addedge(u,v);
__addedge(v,u);
}
void tarjan(int p,int eid)
{
dfn[p]=low[p]=++ind;
for(int i=head[p];i!=0;i=e[i].next)
{
if(i!=(eid^1))
{
int q=e[i].to;
if(!dfn[q])
{
tarjan(q,i);
low[p]=min(low[p],low[q]);
if(dfn[p]<low[q]) bridge[i]=bridge[i^1]=1;
}
else
{
low[p]=min(low[p],dfn[q]);
}
}
}
}
void dfs(int p,int id)
{
bel[p]=id;
for(int i=head[p];i!=0;i=e[i].next)
{
int q=e[i].to;
if(bel[q]) continue;
if(!bridge[i]) dfs(q,id);
}
}
void presolve()
{
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i,0);
}
}
for(int i=1;i<=n;i++)
{
if(!bel[i])
{
dfs(i,++cnt);
}
}
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=0;j=e[j].next)
{
int q=e[j].to;
if(bel[i]!=bel[q])
{
g[bel[i]].push_back(bel[q]);
g[bel[q]].push_back(bel[i]);
}
}
}
}
int dis[N],vis[N];
void dfs2(int p)
{
vis[p]=1;
for(int q:g[p])
{
if(!vis[q])
{
dis[q]=dis[p]+1;
dfs2(q);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>t1>>t2;
addedge(t1,t2);
}
presolve();
dfs2(1);
int p=max_element(dis+1,dis+n+1)-dis;
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
dfs2(p);
int q=max_element(dis+1,dis+n+1)-dis;
cout<<dis[q]<<endl;
}