世纪好题!
无向图缩点的话 在dfs的时候禁止访问父节点就好了,其他与有向图缩点一样。
然后就是求树的直径。
画图想想就理解了,从“必经之路”入手,想到环是造成非必经之路的原因。我们缩完点后得到无环连通图,即一棵树,树上每两个点之间有一条唯一的路径,路径上每条边都是必经之路。
所以只是到 tarjan缩点模板 + 树的直径模板!
好题啊。。。
prev是关键字,所以用的prevv
1 #include<iostream> 2 #include<vector> 3 #include<map> 4 #include<stack> 5 #include<queue> 6 #include<cstring> 7 using namespace std; 8 9 int m1[300005],m2[300005],prevv[300005],low[300005],instack[300005],time; 10 vector<int> edge[300005],edge2[300005]; 11 map<int,int> scc; 12 13 stack<int> s; 14 void tarjan(int u,int last){ 15 prevv[u] = low[u] = ++time; 16 //cout<<u<<" "<<time<<endl; 17 s.push(u); instack[u]=1; 18 for(int i=0;i<edge[u].size();i++){ 19 int v = edge[u][i]; 20 // cout<<"``` "<<u<<" "<<v<<endl; 21 if(v==last) continue;//无向图时禁止访问父结点 22 if( prevv[v]==0 ){ 23 tarjan(v,u); 24 low[u] = min(low[u],low[v]); 25 } 26 else if( instack[v] ) low[u] = min(low[u],prevv[v]); 27 } 28 29 if(prevv[u]==low[u]){ 30 // cout<<"??? "<<s.top()<<" "<<u<<endl; 31 while(s.top()!=u){ 32 int index=s.top(); s.pop(); scc[index]=u; instack[index]=0; 33 } 34 s.pop(); scc[u]=u; instack[u]=0; 35 } 36 } 37 38 int d[300005]; 39 queue<pair<int,int> > q; 40 void bfs(int s){ 41 memset(d,-1,sizeof(d)); 42 q.push( make_pair(s,0) ); 43 d[s]=0; 44 while(!q.empty()){ 45 pair<int,int> p = q.front(); q.pop(); 46 int index=p.first,length=p.second; 47 d[index]=length; 48 for(int i=0;i<edge2[index].size();i++){ 49 int v=edge2[index][i]; 50 if(d[v]==-1) q.push(make_pair(v,length+1));//继续bfs 51 } 52 } 53 } 54 55 int main(){ 56 int n,m; scanf("%d%d",&n,&m); 57 for(int i=1;i<=m;i++){ 58 scanf("%d%d",&m1[i],&m2[i]); 59 edge[m1[i]].push_back(m2[i]); 60 edge[m2[i]].push_back(m1[i]); 61 } 62 63 tarjan(1,0);//无向图缩点 64 // for(int i=1;i<=n;i++) cout<<"!!! "<<i<<" "<<scc[i]<<endl; 65 66 for(int i=1;i<=m;i++){ 67 if( scc[ m1[i] ]==scc[ m2[i] ] ) continue; 68 else{ 69 edge2[ scc[m1[i]] ].push_back( scc[m2[i]] ); 70 edge2[ scc[m2[i]] ].push_back( scc[m1[i]] ); 71 } 72 } 73 74 //树的直径 75 bfs(1); 76 int maxd=1; 77 for(int i=2;i<=n;i++){ 78 if( d[i]>d[maxd] ) maxd=i; 79 } 80 bfs(maxd); 81 82 int ans=d[1]; 83 for(int i=2;i<=n;i++){ 84 if( d[i]>ans ) ans=d[i]; 85 } 86 cout<<ans; 87 88 return 0; 89 }