Tarjan(四) eDCC缩点

eDcc(边双联通分量)缩点

在无向图中,不含割边的联通块便是边双联通分量。在边双联通分量中,每个点之间至少两条以上路径到达另外一点

在一张连通的无向图中,对于两个点u和v,如果无论删去哪条边(只能删去一条)都不能使它们不连通,我们就说u和v边双连通

根据上一篇文章讲过关于割边的方法,这里同样缩点,记录下割边,割边的两端一定死缩点后的新点,所以用记录的割边来给新的点分配出入度,度数为1的点自然就是新树的叶子节点
在这里插入图片描述

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
const int N = 1e4 + 10, M = 2e5 + 10;
struct edge{
    int u, v;
};
vector<edge> e;
vector<int> h[N];
int n, m;
int dfn[N], low[N], tot;
int bri[N], cnt;
int edcc[N], idx, d[N];
stack<int> stk;

void add(int a, int b) {
    e.push_back({a, b});
    h[a].push_back(e.size() - 1);
}
void tarjan(int x, int din) {
    dfn[x] = low[x] = ++tot;
    cout << "dfn[" << x << "]=" << dfn[x] << '\n';
    stk.push(x);
    for(int i = 0; i < h[x].size(); i++) {
        int j = h[x][i], v = e[j].v;
        if(!dfn[v]) {
            tarjan(v, j);
            low[x] = min(low[x], low[v]);
            cout << "low[" << x << "]=" << low[x] << '\n';
            if(low[v] > dfn[x]) {
                // cout << "gebian: " << e[j].u << ' ' << e[j].v << '\n';
                bri[j] = 1;
                bri[j^1] = 1;
            }
        } else if(din != (j ^ 1)) { //这里一定要注意加括号,没加括号一直错
            low[x] = min(low[x], dfn[v]);
            cout << "*low[" << x << "]=" << low[x] << '\n';
        }
    }
    if(low[x] == dfn[x]) {
        cout << "eDCC:";
        int y;
        idx ++;
        do{
            y = stk.top(); stk.pop();
            cout << y << ' '; 
            edcc[y] = idx;
        }while(y != x);
        cout << '\n';
    }
}
int main() {
    cin >> n >> m;
    while(m--) {
        int a, b; cin >> a >> b;
        add(a, b); add(b, a);
    }
    tarjan(1, -1);
    for(int i = 0; i < e.size(); i++) {
        if(bri[i]) {
            int v = e[i].v;
            d[edcc[v]]++;
        }
    }
    int ans = 0;
    for(int i = 1; i <= idx; i++) {
        if(d[i] == 1) ans++;
    }
    cout << (ans + 1) / 2; //这是一个结论,缩点后加几条边可以使得这个缩点后的树变成一个联通分量,只需记录叶子结点树,叶子结点为偶数的话,两两相连,为奇数则多出一条,所以要加ans + 1 >> 1条
    return 0;
}

在这里插入图片描述

在这里插入图片描述

视频学习可以去:【D18 Tarjan eDCC 缩点】https://www.bilibili.com/video/BV1MA4y1d7CM?vd_source=4c9eb38d8205116069b961c84f64c958

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幻听嵩的留香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值