#Tarjan,树的直径#CF1000E We Need More Bosses
题目
给定一个\(n\)个点\(m\)条边的无向图,找到两个点\(s,t\),使得\(s\)到\(t\)必须经过的边最多
分析
桥就是必须经过的边,考虑给无向图缩点,
按照桥建一棵树,那么就转换成了求树的直径
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=600011; struct node{int y,next;}e[N<<1],E[N<<1];
int dfn[N],low[N],hs[N],as[N],Et=1,et=1,tot,ext,n,m,bridge[N<<1],col[N],ans,dp[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed min(int a,int b){return a<b?a:b;}
inline signed max(int a,int b){return a>b?a:b;}
inline void tarjan(int x,int F){
dfn[x]=low[x]=++tot;
for (rr int i=hs[x];i;i=E[i].next)
if (!dfn[E[i].y]){
tarjan(E[i].y,i^1);
low[x]=min(low[x],low[E[i].y]);
if (dfn[x]<low[E[i].y])
bridge[i]=bridge[i^1]=1;
}else if (i!=F) low[x]=min(low[x],dfn[E[i].y]);
}
inline void add(int x,int y){
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
inline void dfs(int x){
col[x]=ext;
for (rr int i=hs[x];i;i=E[i].next)
if (!bridge[i]&&!col[E[i].y]) dfs(E[i].y);
else if (bridge[i]&&col[E[i].y])
add(ext,col[E[i].y]);
}
inline void Dfs(int x,int fa){
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fa){
Dfs(e[i].y,x);
ans=max(ans,dp[e[i].y]+dp[x]+1);
dp[x]=max(dp[x],dp[e[i].y]+1);
}
}
signed main(){
ext=n=iut(),m=iut();
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut();
E[++Et]=(node){y,hs[x]},hs[x]=Et;
E[++Et]=(node){x,hs[y]},hs[y]=Et;
}
for (rr int i=1;i<=n;++i)
if (!dfn[i]) tarjan(i,0);
for (rr int i=1;i<=n;++i)
if (!col[i]) ++ext,dfs(i);
Dfs(ext,0);
return !printf("%d",ans);
}