【算法笔记】基环树

整理的算法模板合集: ACM模板


基环树

基环树(基于环的树 ),也是环套树,是一种有 n n n 个点 n n n 条边的图,简单地讲就是树上在加一条边。它形如一个环,环上每个点都有一棵子树的形式。

基环内向树:每个点出度为1(因此每个环上点的子树,儿子指向父亲)

基环外向树:每个点入度为1(因此每个环上点的子树,父亲指向儿子)

基环树的关键就是找到环,可以先把环当作这个无根树的 “根” ,也就是把环当成一个点(先不管它),这样一颗基环树就变成了一个普通的树,然后我们先按照解决普通树的方法对“根”的所有子树依次处理求解答案,最后在单独对环上所有的点进行操作求解最终答案即可。

找环的两种方式

拓扑排序

处理无向图

可以找出环上的所有点。

void topsort(){
   
    int l=0,r=0;
    for (int i=1;i<=n;i++) 
      if(in[i]==1) q[++r]=i;
    while(l<r) {
   
        int now=q[++l];
        for (int i=ls[now];i;i=a[i].next){
   
            int y=a[i].to;
            if(in[y]>1){
   
                in[y]--;
                if(in[y]==1) q[++r]=y;
            }
        }
    }
}

之后入度 > = 2 >=2 >=2 的点就是环上的点

dfs

处理有向图,码量小

void check_c(int x)
{
   
    v[x]=true;
    if(v[d[x]]) mark=x;//环上的一点
    else check_c(father[x]);
    return;
}

我们稍加修改就可以保存所有的环上的节点了。

inline bool dfs(int x, int in_edge)
{
   
    if(v[x] == 1){
   //再次访问说明到了环的链接点,标记它是环(v[x] = 2)
        v[x] = 2, loop[++ cnt] = x, v2[x] = 1;
        return true;
    }
    v[x] = 1;
    for(int i = head[x]; ~i; i = nex[i]){
   
        int y = ver[i];
        //如果当前边不是上一条边(没有往回走)并且当前节点在环上
        if(i != ((in_edge) ^ 1) && dfs(y, i)){
   //每次存一个点,靠继续dfs遍历整个环
            if(v[x] != 2)//当前节点不是衔接点,把环里的点存起来
                loop[++ cnt] = x, v2[x] = 1, s[cnt] = s[cnt - 1] + edge[i];
            else {
   //环的链接点
                s[st - 1] = s[st] - edge[i];//又转回来(破环成链)
                return
  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

繁凡さん

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

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

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

打赏作者

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

抵扣说明:

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

余额充值