首页 > 其他分享 >基环树

基环树

时间:2024-06-11 12:59:58浏览次数:16  
标签:return int long 基环树 dfs dp

基环树的定义为:一个有向或无向图中,只含有一个环的图,形式化的表达为:

关于这种形状关键点主要在于找环,那么我们可以一步一步的去寻找,当这个点走着走着走到了某个环里,我们可以直接遍历整个环,然后打个标记,这样环就找到了
具体的例题:
E - Reachability in Functional Graph
本题就是一个基环树森林,即不同的连通块,每个块内可能存在一个基环树,那么我们直接暴力的找出来每个环,并且算出环的节点个数,那么每个点的贡献就是,从这个点出发到环内某一节点经过的边数+环的大小,然后再直接进行记忆化搜索即可:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n; cin>>n;
    vector<int>a(n+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    vector<int>vis(n+1),dp(n+1); // vis 数组是用来标记这个点是否被遍历过
                                // dp 环中每个点的贡献
    for(int i=1;i<=n;i++){
        if(vis[i]) continue; //如果被遍历到了,直接跳过
        int u=i;
        while(true){ //一直遍历下去
            if(vis[u]){ 
                if(vis[u]==i){ //如果是第一次被标记,也就是某个环的入口,我们就计算一下这个环
                    int x=a[u],cnt=1;
                    while(x!=u){ //走回来就停止
                        cnt++,x=a[x];
                    }
                    dp[u]=cnt,x=a[u];
                    while(x!=u){
                        dp[x]=cnt,x=a[x]; //每个节点的贡献都是这个环的大小
                    }
                    break;
                }
            }
            vis[u]=i,u=a[u]; //向下传点
        }
    }
    function<int(int)>dfs;
    dfs=[&](int u)->int{
        if(dp[u]) return dp[u];
        return dp[u]=dfs(a[u])+1;
    };
    int res=0;
    for(int i=1;i<=n;i++) res+=dfs(i);
    cout<<res;
    return 0;
}

标签:return,int,long,基环树,dfs,dp
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/18241874

相关文章

  • 基环树找环
    abc167_dTeleporter#include<bits/stdc++.h>#defineptprintf(">>>")#definemid(((l)+(r))/2)usingnamespacestd;typedeflonglongll;typedeflongdoubleld;constllN=1e6+10,inf=1e18+10,mod=1e9+7;vector<ll>G[N];map&......
  • 置换 & 基环树题
    T1Statement给一个长度为\(n(\le10^5)\)的排列\(\{a_i\}\)。求一个排列\(\{b_i\}\),使得\(a_i=b_{b_i}\),或输出不存在。Solution先把所有排列变成置换对于任意排列\(\{p_i\}\),它转成置换后都是\(i\top_i\),故有\(i\top_i\top_{p_i}\top_{p_{p_i}}\to...\)所以所有......
  • 基环树算法总结
    基环树算法总结一、什么是基环树基环树,顾名思义,有两个要素:环和树。因此,基环树就是一棵树的一个节点,扩成一个环,做题时,多棵基环树组成的基环树森林,常以如下方式出现:每个点只有一个出边。每个点只有一个入边。图中一共有\(n\)个点,\(n\)条边。那么,基环树类型的题目应该怎......
  • 基环树
    byDuck.感觉都是神秘乱搞。一般的处理方式:把整个环当成根。断环。CF711DDirectedRoads正难则反,考虑统计成环的数量。我们先把环搜出来,那么环上的边只能有全部顺时针或者全部逆时针两种方向,环外的边任意。设环长为\(L\),那么就有\(2^{n-L}\times2\)种有环的情况,从而......
  • 基环树小结
    基环树就是根节点基于环生长的一棵树,特点是\(n\)个节点\(n\)条边。如果\(n\)个节点\(n\)条边的图不联通那么是一个基环森林。很好证明,\(n\)个点\(n-1\)条边的联通图仅能是一棵树,现在从任一点引出一条边到任一点,由于两点先前一定联通,则在连接后原路径上的任意两点均有......
  • 关于基环树的一切
    观前须知笔者的博客主页声明本文使用CCBY-NC-SA4.0许可。本文为笔者在OI学习中的复习向学习笔记。部分内容会比较简略。如有好的习题会不断补充。知识简介定义基环树是一个有\(n\)个点\(n\)条边的连通图。因为树有\(n\)个点\(n-1\)条边。所以基环树可以......
  • 基环树
    1基环树概念1.1定义首先,基环树并不是一颗严格的树。它是一张由\(n\)个节点,\(n\)条边组成的图。1.2无向联通图上的基环树首先,一棵树有\(n\)个节点,\(n-1\)条边。那么基环树就可以看做是在一棵树上加了一条边,这样多出了一个环(因此基环树也被称作环套树)。如下图所示:1.......
  • 基环树学习笔记
    基环树学习笔记定义基环树指的是一张有\(n\)个节点和\(n\)条边的图,如果不保证连通的话,那么整张图是一张基环树森林。并且如果将环上的任意一条边去除,那么整棵基环树会成为一棵普通的树。分类基环树有以下几种特殊情况,也是题目中较多出现的。基环内向树指的是在一棵有向......
  • 基环树学习笔记
    1.定义基环树,又称环套树,n个点n条边,也就是一棵树多一条边,形成唯一的环,这是保证这n个点n条边构成的是一个连通图的时候才是唯一环,如果图不连通但是每个连通块点数都等于边数的时候这个图就是一个基环树森林,可以有多个环如果一张有向弱连通图每个点的入度都为1,则称它是一棵基环外......
  • 【图论】基环树 学习笔记
    基环树下面几个条件互相等价:一个图(连通块)是基环树联通块有n个点n条边图上存在且仅存在一个环,且环上每个节点是一颗子树的根。通常情况下树指的都是无向图,但是有向图也可以构成基环树。内向基环树:每个点都有一条出边。容易发现沿着这条边一定会走到环上“向内走”。外......