题意: 求一个无向图缩点后,求直径长度
注意无向图强连通和有向图强连通是有区别的,主要是无向图强连通不能回头,要求在tarjan算法里记录father
#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=3e5+5;
const int MOD=1e9+7;
ll a[N],sum[N],dis[N];
int par[N];
int vis[N];
vector<pair<ll,ll> > edge[N];
vector<ll> bet;
vector<ll> maxsubtree;
vector<ll> diameter;
ll maxlen=0,k,st,ed;
int n,m,cur,cnt,top,mp[N],DFN[N],LOW[N],s[N];
void tarjan(int u,int f){
DFN[u]=LOW[u]=++cur;
s[++top]=u;
for(int i=0;i<(int)edge[u].size();i++){
int v=edge[u][i].F;
if(v==f) continue;
if(!DFN[v]){
tarjan(v,u);
LOW[u]=min(LOW[u],LOW[v]);
}
else if(DFN[v] && !mp[v]) LOW[u]=min(LOW[u],DFN[v]);
}
if(DFN[u]==LOW[u]){
int v=-1;
cnt++;
while(u!=v){
v=s[top--];
mp[v]=cnt;
}
// puts("************");
}
}
void dfs(int u,int f){
par[u]=f;
for(auto t:edge[u]){
int v=t.F;
if(v==f) continue;
dis[v]=dis[u]+1;
dfs(v,u);
}
}
void FindDiameter(){
memset(dis,0,sizeof dis);
dfs(1,-1);
ll mx=-1;
for(int i=1;i<=n;i++)
if(dis[i]>mx) mx=dis[i],st=i;
memset(dis,0,sizeof dis);
dfs(st,-1);
mx=-1;
for(int i=1;i<=n;i++)
if(dis[i]>mx) mx=dis[i],ed=i;
for(int i=ed;i!=-1;i=par[i]) diameter.pb(i);
reverse(diameter.begin(),diameter.end());///find the diameter of the tree
return ;
}
pair<int,int> p[N];
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
ll u,v,w;
cin>>u>>v;
w=1;
p[i]={u,v};
edge[u].pb({v,w});
edge[v].pb({u,w});
}
for(int i=1;i<=n;i++)
if(!DFN[i]) tarjan(i,-1);
// cout << "cnt="<<cnt<<endl;
for(int i=1;i<=n;i++) edge[i].clear();
// for(int i=1;i<=n;i++) cout << "mp["<<i<<"]="<<mp[i]<<endl;
for(int i=1;i<=m;i++){
int u=p[i].F,v=p[i].S;
// cout <<u << " "<<mp[u]<<" "<<v<<" "<<mp[v]<<endl;
if(mp[u]==mp[v]) continue;
else{
edge[mp[u]].pb({mp[v],1ll});
edge[mp[v]].pb({mp[u],1ll});
}
}
n=cnt;
FindDiameter();
cout << (int)diameter.size()-1<<endl;
return 0;
}