Codeforces 1000E We Need More Bosses 【无向图缩点】【树的直径】

世纪好题!

无向图缩点的话 在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 }

猜你喜欢

转载自www.cnblogs.com/ZhenghangHu/p/9281675.html