基环树求环基本思路
作者:互联网
什么是基环树?
n条边,n个点,连在一起,就变成了基环树
基环树如何求环?
有人用拓扑排序,但是如果不苛求时间复杂度,可以直接利用栈的思想和dfs进行找环
步骤?
第一步:寻找(任意)一个点进行一次dfs(1,0)
第二步:将所有dfs到的点,存入到栈中
第三步:直到发现连接的点已经访问过了,这时候就相当于找到了一个环
由于dfs的特性,这个时候你只是一直访问了一个路径,一直出栈,相当于就是在你dfs的路径上跳出刚才刚刚找到的点
一直出栈到你发现已经访问过的点
第四步:标记
第五步:对于每一个在环上的点,进行dfs(不在环上,且未dfs过的点)
这个时候dep数组就可以直接输出了
CF131D Subway
1 #include <cstdio> 2 3 const int MAXN=(int)1e4+5; 4 int ver[MAXN<<1],next[MAXN<<1],head[MAXN],tot; 5 6 void add(int u,int v){ 7 ver[++tot]=v,next[tot]=head[u],head[u]=tot; 8 } 9 10 int sta[MAXN],top,cir[MAXN]; 11 bool vis[MAXN],flag; 12 13 void getcir(int x,int fa){ 14 if(flag) return; 15 sta[++top]=x,vis[x]=true; 16 for(int i=head[x];i;i=next[i]){ 17 int y=ver[i]; 18 if(y==fa) continue; 19 if(vis[y]) 20 { 21 cir[y]=true; 22 while(sta[top]!=y){ 23 cir[sta[top--]]=true; 24 } 25 flag=true; 26 return; 27 } 28 getcir(y,x); 29 top--,vis[y]=false; 30 } 31 } 32 33 int dep[MAXN]; 34 void getdep(int x){ 35 for(int i=head[x];i;i=next[i]){ 36 int y=ver[i]; 37 if(dep[y] || cir[y]) continue; 38 dep[y]=dep[x]+1; 39 getdep(y); 40 } 41 } 42 43 int main(){ 44 int n,u,v; 45 scanf("%d",&n); 46 for(int i=1;i<=n;i++) 47 { 48 scanf("%d%d",&u,&v); 49 add(u,v),add(v,u); 50 } 51 getcir(1,0); 52 for(int i=1;i<=n;i++) 53 { 54 if(cir[i]!=false) dep[i]=0,getdep(i); 55 } 56 for(int i=1;i<=n;i++) printf("%d ",dep[i]); 57 }
标签:出栈,环上,int,dfs,基环树求,基环树,MAXN,基本思路 来源: https://www.cnblogs.com/rign/p/10803426.html