Tarjan 算法应用标程
模拟赛不会写点双开了挂,现在复习一下
Tarjan 算法应用标程
变量解释:
| 名称 | 用途 | 类型 |
|---|---|---|
| \(dfn\) | 时间戳 | int[] |
| \(low\) | 回溯最早时间戳 | int[] |
| \(child\) | 孩子数 | int[] |
| \(ti\) | 时间 | int |
| \(s\) | 源点 | int |
| \(nme\) | 所属连通分量 | int[] |
| \(cut\) | 是否是割 | bool[] |
| \(cnt\) | 连通分量数 | int |
| \(d(s)cc\) | 连通分量所含点 | vector<int>[] |
| \(ins\) | 是否在栈中 | bool[] |
| \(tp\) | 栈顶 | int |
| \(x\) | 栈顶元素 | int |
割边与边双连通分量(\(e-dcc\))
//割边
void Tarjan(int u,int e){
low[u] = dfn[u] = ++ti;
for(int i = head[u];~i;i = edge[i].nxt){
//链式前向星存图, 终点指向 -1
int v = edge[i].to;
if(!dfn[v]){
Tarjan(v,i);
low[u] = min(low[u],low[v]);
if(low[v] > dfn[u])
cut[i] = cut[i ^ 1] = 1;
}
else if(i != (e ^ 1))
//各条边的名字从 0 开始,
//使 0 与 1 配对,2 与 3 配对……
low[u] = min(low[u],dfn[v]);
}
}
void DFS(int u){//加上就是边双缩点
dcc[cnt].push_back(u);//cnt 在主函数累加
nme[u] = cnt;
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(cut[i]) continue;
DFS(v);
}
}
割点与点双连通分量(\(v-ecc\))
//割点
void Tarjan(int u){
low[u] = dfn[u] = ++ti;
int child = 0;
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(!dfn[v]) {
Tarjan(v);
low[u] = min(low[u],low[v]);
if(low[v] >= dfn[u]){
child++;
if(u != s || child >= 2)
//源点在主函数遍历
cut[u] = true;
}
}
else low[u] = min(low[u],dfn[v]);
}
}
//点双
void Tarjan(int u){
dfn[u] = low[u] = ++ti;
st[++tp] = u;
if(u == s && head[u] == -1){
dcc[++cnt].push_back(u);
return;
}
int child = 0;
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(!dfn[v]){
Tarjan(v);
low[u] = min(low[u],low[v]);
if(low[v] >= dfn[u]){
child++;
if(u != s || child > 1) cut[u] = 1;
cnt++; int x;
do{
x = st[tp--];
dcc[cnt].push_back(x);
} while(x != v);
dcc[cnt].push_back(u);
}
}
else low[u] = min(low[u],dfn[v]);
}
}
强连通分量(\(scc\))
//强
void Tarjan(int u){
dfn[u] = low[u] = ++ti;
ins[u] = 1; st[++tp] = u;
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(!dfn[v]){
Tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(ins[v])
low[u] = min(low[u],dfn[v]);
}
if(dfn[u] == low[u]){
++cnt; int x;
do{
x = st[tp--]; ins[x] = 0;
nme[x] = scc; scc[cnt].insert(x);
} while(x != u);
}
}

浙公网安备 33010602011771号