时间复杂度为O(n+m)
黑匣子:
先最初调用
1、init()
2、把图用add 存下来,注意图点标为1-n,若是[0,n-1]则给所有点++;
3、调用tarjan_init(n); 再调用suodian();
4、新图就是vector<int>G[]; 新图点标从1-tar ;
5、对于原图中的每个点u,都属于新图中的一个新点Belong[u];
新图一定是森林。
6、新图中的点u 所表示的环对应原图中的vector<int> bcc[u];
7、旧图中u在新图中所属的点是Belong[u];
#define N 30100
//N为最大点数
#define M 150100
//M为最大边数
int n, m;//n m 为点数和边数
struct Edge{
int from, to, nex;
bool sign;//是否为桥
}edge[M<<1];
int head[N], edgenum;
void add(int u, int v){//边的起点和终点
Edge E={u, v, head[u], false};
edge[edgenum] = E;
head[u] = edgenum++;
}
int DFN[N], Low[N], Stack[N], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)
int taj;//连通分支标号,从1开始
int Belong[N];//Belong[i] 表示i点属于的连通分支
bool Instack[N];
vector<int> bcc[N]; //标号从1开始
void tarjan(int u ,int fa){
DFN[u] = Low[u]