Tarjan
强连通
定义:
有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。
如果有向图G的每两个顶点都强连通,称G是一个强连通图。
有向图的极大强连通子图,称为强连通分量(strongly connected components)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void tarjan(int cur){ 2 dfn[cur] = low[cur] = ++t_cnt; 3 stack[++s_size] = cur; instack[cur] = 1; 4 for(int i = head[cur]; i != -1; i = edge[i].next){ 5 int v = edge[i].v; 6 if(!dfn[v]){ 7 tarjan(v); 8 low[cur] = min(low[cur], low[v]); 9 } 10 else if(instack[v])//栈里的是来时路上的点 当然可以到达当前点 所以可以更新 11 low[cur] = min(low[cur], low[v]); 12 } 13 if(dfn[cur] == low[cur]){ 14 col_size++; 15 do{ 16 int temp = stack[s_size]; 17 color[temp] = col_size; 18 instack[temp] = 0; 19 }while(stack[s_size--] != cur); 20 } 21 }
双联通
双连通分量又分 点双连通分量 和 边双连通分量 两种。
若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图。
说白了就是找环啦
一个无向图中的每一个极大点(边)双连通子图称作此无向图的点(边)双连通分量。
这里就不附带代码了 因为和找割点极为类似
缩点
其实就是把一个强连通分量缩成一个点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void tarjan(int cur){ 2 dfn[cur] = low[cur] = ++t_cnt; 3 stack[++s_size] = cur; instack[cur] = 1; 4 for(int i = head[cur]; i != -1; i = edge[i].next){ 5 int v = edge[i].v; 6 if(!dfn[v]){ 7 tarjan(v); 8 low[cur] = min(low[cur], low[v]); 9 } 10 else if(instack[v]) 11 low[cur] = min(low[cur], low[v]); 12 } 13 if(dfn[cur] == low[cur]){ 14 col_size++; 15 do{ 16 int temp = stack[s_size]; 17 color[temp] = col_size; 18 nw[col_size] += w[temp];//只多这一句话 19 instack[temp] = 0; 20 }while(stack[s_size--] != cur); 21 } 22 }
割点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void tarjan(int x, int fa){ 2 int ch = 0; 3 dfn[x] = low[x] = ++t_cnt; 4 for(int i = head[x]; i != -1; i = edge[i].next){ 5 int vv = edge[i].v; 6 if(vv == fa)continue; 7 if(!dfn[vv]){ 8 ch++; 9 tarjan(vv, x); 10 low[x] = min(low[x], low[vv]); 11 if(low[vv] >= dfn[x]) cut[x] = 1; 12 } 13 low[x] = min(low[x], dfn[vv]);//关键是这里!与强连通不同 14 } 15 if(fa == -1 && ch <= 1) cut[x] = 0; 16 }
lca
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void tarjan(int x){ 2 vis[x] = 1; 3 for(int i = head[x]; i != -1; i = edge[i].next){ 4 int vv = edge[i].v; 5 if(vis[vv]) continue; 6 tarjan(vv); 7 fa[vv] = x; 8 } 9 for(int i = hq[x]; i != -1; i = q[i].next){ 10 int vv = q[i].v; 11 if(vis[vv]) ans[q[i].id] = find(vv); 12 } 13 }
相关题目: