模板【强连通分量缩点】
作者:互联网
PART1(算法思想简介)
1.实现:
因为一个点只属于一个强连通分量
具体的操作方法如下,遍历原图上的每一条边,如果两个点不属于同一个强连通分量,然后在新图上的这两个强连通分量之间建一条有向边。
(新图是一个多重图)
2.时间复杂度:
3.特别优势:
最后弄成了一个有向无环图,DAG
4.适用情况:
5.需要注意的点:
6:函数、变量名的解释+英文:
PART2(算法各种类型(并附上代码))
#include<cstdio> #include<cmath> #include<algorithm> #include<set> #include<map> #include<cstring> #include<string> #include<vector> #include<queue> #include<iomanip> #include<iostream> #include<stack> using namespace std; #define inf 0x3f3f3f3f const int N = 1e2+10; const int M = 1e4+10; //与边相关 struct edgeK { int u, v, next, w; } eK[M]; int pK[N], eidK; inline void InitEdgeK() { memset(pK, -1, sizeof(pK)); eidK = 0; } inline void InsertK(int u, int v, int w = 0) { eK[eidK].next = pK[u]; eK[eidK].u = u; eK[eidK].v = v; eK[eidK].w = w; pK[u] = eidK++; } //强连通分量 int timeStamp = 0; int dfn[N], low[N]; int sccCnt = 0;//强连通分量的数量 int sccId[N];//记录每个点属于的强连通分量的编号 set<int> scc[N]; stack<int> sBcc; void DfsScc(int u) { dfn[u] = low[u] = ++timeStamp; sBcc.push(u); for(int i = pK[u]; i != -1; i = eK[i].next) { int v = eK[i].v; if(dfn[v] == 0)//没有被访问过 { DfsScc(v); low[u] = min(low[u], low[v]); } //在别人的强连通分量里面 else if(!sccId[v])//对于已经求出scc的点,直接 { low[u] = min(low[u], dfn[v]); } } //一个点是一个强连通分量里面最先发现的点(此时他的子节点已经访问好了),就把此强连通分量存好 if(low[u] == dfn[u]) { ++sccCnt; while(true) { int x = sBcc.top(); sBcc.pop(); sccId[x] = sccCnt; scc[sccCnt].insert(x); if(x == u) break; } } } //缩点 struct edge { int v, next, w; } e[M]; int p[N], eid; inline void InitEdge() { memset(p, -1, sizeof(p)); eid = 0; } inline void Insert(int u, int v, int w = 0) { e[eid].next = p[u]; e[eid].v = v; e[eid].w = w; p[u] = eid++; } int main() { //freopen("in.txt","r", stdin); //freopen("out.txt","w", stdout); ios::sync_with_stdio(false); InitEdgeK(); int n, m; cin >> n >> m; for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; InsertK(u, v); } memset(dfn, 0, sizeof(dfn)); memset(sccId, 0, sizeof(sccId)); timeStamp = sccCnt = 0; //有向图不能保证访问到每一个点 for(int i = 1; i <= n; i++) { if(!dfn[i]) DfsScc(1); } InitEdge(); for(int u = 1; u <= n; ++u) { for(int i = p[u]; i != -1; i = e[i].next) { int v = e[i].v; if(sccId[u] != sccId[v]) { Insert(sccId[u], sccId[v]); } } } return 0; }View Code
PART3(算法的延伸应用)
PART4(对算法深度的理解)
PART5(与其相关的有趣题目)
标签:缩点,连通,eK,int,dfn,low,include,模板 来源: https://www.cnblogs.com/bear-xin/p/14966267.html