首页 > 其他分享 >学习笔记——缩点

学习笔记——缩点

时间:2024-02-08 11:22:48浏览次数:27  
标签:缩点 Tarjan int 笔记 学习 dfn low 权值

前置知识:Tarjan 求强连通分量

一、什么是缩点

缩点,就是把一张有向有环图上的一个个环缩成点,使其变成有向无环图。

二、缩点的应用

  • 求最长路时常用。

  • 标准问法:

给定一个有向图,每个点有一个权值,允许多次经过一条边或者一个点,重复经过的点,权值只计算一次。求最大权值

若直接用最段路模板改,则会在一个圈子里面一直绕,出不来。所以我们要用缩点,把一个圈缩成一个点,再去求解。

观察下面这张图:

我们会发现,图中点 \(1,3,5\) 形成一个闭环(强连通分量),显然,如果要让这张图的权值最大,我们要把他们都经过一遍。所以缩点,然后把每个点的权值相加。缩完点的图如下:

此点权值为 \(9\)。

三、环的判定

既然我们知道了,有环才能进行缩点,那么怎么判定环呢?先上结论:

当 \(dfn[u]=low[u]\) 时,则点 \(u\) 必然是环上的一点。

为什么?在 Tarjan 求强连通分量的过程中,我们任意一个节点 \(u\) 的 \(low\) 一直在和它的子结点 \(v\) 的 \(low\) 取最小值。那什么情况下, \(low[u]\) 会在取完最小值后仍然和 \(dfn[u]\) (此点的 dfs 序)相等?只能是在 \(u\) 的子树中,有一条返祖边,又指回了 \(u\) 。那么在这种情况下,\(u\) 的子树中部分点和 \(u\) 就成为了一个环。

四、如何进行缩点

在 Tarjan 求强连通分量的基础上,我们在代码中加入一个栈 \(STA\),用来存放此次 dfs 遍历过的点的编号。另外加入一个标识数组,如果这个点已经在栈中,就不再把它入栈。

当我们判定点 \(u\) 是环中一点时,则栈中且在点 \(u\) 第一次出现之后被压入栈的点一定和点 \(u\) 成为一个环(历经这些点,又环回了 \(u\))。那么只需要把 \(STA\) 中的这些点作 pop 操作,然后将点权加总,将这些点染上同一个颜色。在所有点 dfs 一遍之后,把颜色不同的点集重新建图连边就可以了(新图每个点集的连边包括原来环上所有点连的所有边)。

核心代码:

//Tarjan算法

void tarjan(int x){
    dfn[x]=low[x]=++num;
    sta[++top]=x, vis[x]=1; //每个点入栈
    //常规求强连通分量
    for (int i=head[x]; i; i=nxt[i]){
        int y=ver[i];
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x], low[y]);
        }
        else if(vis[y]) low[x]=min(low[x], dfn[y]);
    }
    //判定环
    if(low[x]==dfn[x]){
        int y;cnt++;
        //每点弹出栈,到再次遇到点 x 停止
        while(sta[top+1]!=x){
            y=sta[top--];
            col[y]=cnt; //染相同颜色
            vis[y]=0; //标识数组清零
            vsum[cnt]+=p[y]; //权值加和
        }
    }
}

//以下代码添加在main函数中

    tot=0;
    memset(head, 0, sizeof head);
    memset(nxt, 0, sizeof nxt);
    memset(ver, 0, sizeof ver); //清空原图
    for (int i=1; i<=m; i++){  //枚举每一条原边
        int x=col[u[i]], y=col[v[i]]; //每条边的两端点的染色
        if(x!=y) add(x, y); //两端点染色不同,新图里加入连边
    }

标签:缩点,Tarjan,int,笔记,学习,dfn,low,权值
From: https://www.cnblogs.com/ylc666/p/18011673

相关文章

  • $.ajax参数笔记
    $.ajax是jQuery中用于执行AJAX(AsynchronousJavaScriptandXML)请求的方法。这个方法允许你与服务器进行异步通信,获取或发送数据,而不需要重新加载整个页面。下面是$.ajax方法的参数详解:url类型:String描述:请求的地址(默认为当前页地址)。type类型:String描述:请求方式(post......
  • LGV引理学习笔记
    ReferenceOI-wiki介绍LGV引理(Lindström–Gessel–Viennotlemma)用来解决有向无环图上不相交路径计数,注意仅适用于有向无环图。给定\(n\)个起点构成的集合\(S\)和\(n\)个终点构成的集合\(T\),定义\(\omega(P)\)表示路径\(P\)上所有边权的乘积(计数时设边权为\(1\)......
  • 特征多项式学习笔记
    介绍了方阵的特征多项式以及利用上Hessenberg矩阵的\(\mathcal{O}(n^3)\)求法。ReferenceOI-wiki特征多项式:Hessenberg法及加速矩阵幂特征值与特征向量给定\(n\timesn\)的方阵\(\mathbf{T}\),若存在一个非零列向量\(\mathbf{v}\)和数\(\lambda\)满足\(\mathbf{T}......
  • 机器学习之最小二乘法
    最小二乘法概述最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能......
  • 读千脑智能笔记07_人工智能的未来(中)
    1.      机器智能的未来1.1.        没有任何技术原因阻止我们创造智能机器1.1.1.          障碍在于我们缺乏对智能的理解,也不知道产生智能所需的机制1.2.        历史表明,我们无法预测将推动机器智能向前发展的技术进步1.2.1.    ......
  • 树链剖分学习笔记
    树链剖分,计算机术语,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结构(树状数组、BST、SPLAY、线段树等)来维护每一条链。——百度百科重链剖分概念1重儿子一个父节点的所有儿子中,子树节点最大(siz最大)的节点。记......
  • 机器学习如何改变缺陷检测的格局?
    机器学习在缺陷检测中扮演着重要的角色,它能够通过自动学习和识别各种缺陷的模式和特征,改变缺陷检测的格局。以下是机器学习在缺陷检测中的一些应用和优势:自动化检测:机器学习技术可以自动化处理大量的数据,通过学习和识别缺陷的模式和特征,实现自动化检测。这大大提高了缺陷检测的......
  • 【CPL-2023】W14笔记-程序结果、预处理与I/O
    有趣的预编译编写大型程序头文件:变量的声明,函数的声明,宏的定义,预编译指令include库函数include<xx.h>找库函数的路径include自己的头文件include"xx.h",先找当前目录gcc--verbosemain.cgcc-I.include当前目录头文件的重复包含标准头文件结构#ifndef......
  • docker学习的时候敲的历史命令。两百多条
    sudoaptlist|grep-idockercurlhttps://registry-1.docker.io/v2/sudodockerstatussudodockerstatssudodockerpssudodockerps-asudodockerstartebb9831a05fdsudodockerpssudodockerstopebb9831a05fdsudodockerps-asudodockerrun-d......
  • 洛谷P3455 笔记
    传送门又是一道看了tj的题。题意\(t\)次询问,每次询问给定\(n\),\(m\),\(k\),求\(\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=k]\)。\(1\let\le5\times10^4\),\(1\lek\len\),\(m\le5\times10^4\)正文把\(k\)扔到上界去,记原式变为\(\sum_{i=1}^{\lfloor\frac{n}{k}......