cf1000E We Need More Bosses (tarjan缩点+树的直径)
题意:无向联通图,求一条最长的路径,路径长度定义为u到v必须经过的边的个数
如果把强联通分量都缩成一个点以后,每个点内部的边都是可替代的;而又因为这是个无向图,缩完点以后就是棵树,跑两遍dfs求直径即可
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=3e5+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int eg[maxn*2][2],egh[maxn],ect; 16 int eg2[maxn*2][2],egh2[maxn],ect2; 17 int N,M,dfn[maxn],tot,low[maxn],stk[maxn],sh,bel[maxn]; 18 int ma,xx; 19 bool instk[maxn]; 20 21 inline void adeg(int a,int b){ 22 eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect; 23 } 24 inline void adeg2(int a,int b){ 25 eg2[++ect2][0]=b,eg2[ect2][1]=egh2[a],egh2[a]=ect2; 26 } 27 28 void tarjan(int x,int f){ 29 dfn[x]=low[x]=++tot;instk[x]=1;stk[++sh]=x; 30 for(int i=egh[x];i;i=eg[i][1]){ 31 int b=eg[i][0];if(b==f) continue; 32 if(!dfn[b]) tarjan(b,x),low[x]=min(low[x],low[b]); 33 else if(instk[b]) low[x]=min(low[x],dfn[b]); 34 } 35 if(dfn[x]==low[x]){ 36 while(1){ 37 bel[stk[sh]]=x,instk[stk[sh]]=1; 38 if(stk[sh--]==x) break; 39 } 40 } 41 } 42 43 void dfs(int x,int f,int dis){ 44 if(dis>ma) ma=dis,xx=x; 45 for(int i=egh2[x];i;i=eg2[i][1]){ 46 int b=eg2[i][0]; 47 if(b==f) continue; 48 dfs(b,x,dis+1); 49 } 50 } 51 52 int main(){ 53 int i,j,k; 54 N=rd(),M=rd(); 55 for(i=1;i<=M;i++){ 56 int a=rd(),b=rd(); 57 adeg(a,b);adeg(b,a); 58 } 59 tarjan(1,0); 60 for(i=1;i<=N;i++){ 61 for(j=egh[i];j;j=eg[j][1]){ 62 int b=eg[j][0]; 63 if(bel[i]==bel[b]) continue; 64 adeg2(bel[i],bel[b]); 65 } 66 } 67 ma=0;xx=bel[1]; 68 dfs(bel[1],0,0); 69 dfs(xx,0,0); 70 printf("%d\n",ma); 71 return 0; 72 }