首页 > 其他分享 >连通性相关

连通性相关

时间:2024-10-24 15:20:35浏览次数:7  
标签:连通性 int top stk dfn maxn low 相关

强连通

强连通:有向图 \(G\) 中每个点中可互相到达。

强连通分量:极大的强连通。(最大可能的)

求强连通分量

先跑出图的 DFS 搜索树(黑边)。

一个结论:一个强连通分量 一定在该强连通分量中的第一个被访问的点 的子树内。

设根为 \(u\),考虑若存在一个点 \(v\) 不在 \(u\) 子树中则一定存在一条边离开 \(u\) 子树,只可能是返祖/横叉边,显然指向的点已经被标记过了。

Tarjan

一般都用这个。

记 \(dfn(u),low(u)\),后者表示 \(u\) 子树内可以回溯到的节点的 \(dfn\) 最小值(通过走非树边或者 DFS 回溯)。

记一个栈 \(stk\) 表示当前搜索到的节点,对于一个节点 \(v\):

  • \(v\) 未被访问:先算 \(v\) 的答案,再用 \(low(v)\) 更新 \(low(u)\);
  • \(v\) 访问过,且在栈中:用 \(dfn(v)\) 更新 \(low(u)\);
  • \(v\) 访问过,不在栈中:\(v\) 所在连通分量已被处理完。不做操作。

最后只有满足 \(dfn(u)=low(u)\) 的 \(u\) 才能作为结论中的点,据此确定一个强连通分量 \(G=\braket{stk,\cdot}\)。

时间复杂度 \(O(n+m)\)。非常优秀。

int stk[maxn],top;
int dfn[maxn],dfncnt;
int low[maxn];
bool ins[maxn];
int scc[maxn],scccnt;

void tarjan(int u){
    dfn[u]=low[u]=++dfncnt;
    stk[++top]=u; ins[u]=1;
    for(int v:e[u]){
        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]){
        scccnt++;
        while(stk[top]!=u){
            scc[stk[top]]=scccnt;
            ins[stk[top]]=0;
            top--;
        }
        scc[stk[top]]=scccnt;
        ins[stk[top]]=0;
        top--;
    }
}

Kosaraju

黑科技吧。实现非常简单:DFS,以后序遍历(即回溯时编号,相当于反 \(dfn\) 满足 \(rdfn(u)>rdfn(v)(v\in subtree(u))\))标号,在反图上从编号最大的点 DFS,所有遍历到的点即为一个强连通分量。???有点玄幻但的确是对的,马良极小。同样时间复杂度 \(O(n+m)\)。

int scc[maxn],scccnt;
int rdfn[maxn],dfncnt;
bool vis[maxn];
void dfs1(int u){
    vis[u]=1;
    for(int v:e[u]) 
        if(!vis[v]) dfs1(v);
    rdfn[++dfncnt]=u;
}
void dfs2(int u,int col){
    scc[u]=col;
    for(int v:re[u]) 
        if(!scc[v]) dfs2(v);
}
void Kosaraju(){
    for(int i=1;i<=n;i++)
        if(!vis[i]) dfs1(i);
    for(int i=n;i>=1;i--)
        if(!scc[i]) dfs2(rdfn[i],++scccnt);
}

例题:[USACO03FALL / HAOI2006] 受欢迎的牛 G

每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 C 受欢迎。你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。

先缩点,然后找 DAG 上出边为 0 的点,如果不唯一就无解,否则即为那个点包含的连通分量大小。

code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+3;
int n,m;
vector<int>e[maxn];
int stk[maxn],top;
int dfn[maxn],dfncnt,low[maxn];
int scc[maxn],scccnt;
bool ins[maxn];
int out[maxn],siz[maxn];
void tarjan(int u){
    dfn[u]=low[u]=++dfncnt;
    stk[++top]=u; ins[u]=1;
    for(int v:e[u]){
        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]){
        scccnt++;
        while(stk[top]!=u){
            scc[stk[top]]=scccnt;
            ins[stk[top]]=0;
            top--;
            siz[scccnt]++;
        }
        scc[stk[top]]=scccnt;
        ins[stk[top]]=0;
        top--;
        siz[scccnt]++;
    }
}
signed main(){
    cin>>n>>m;
    for(int i=1,u,v;i<=m;i++){
        cin>>u>>v;
        e[u].emplace_back(v);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++){
        for(int j:e[i]){
            if(scc[i]!=scc[j]){
                out[scc[i]]++;
            }
        }
    }
    int oucnt=0,id=0;
    for(int i=1;i<=scccnt;i++){
        if(out[i]==0) oucnt++,id=i;
    }
    if(oucnt>1){
        cout<<0;
    }else{
        cout<<siz[id];
    }
    return 0;
}

标签:连通性,int,top,stk,dfn,maxn,low,相关
From: https://www.cnblogs.com/DEV3937/p/18499268

相关文章

  • 栈的理解及相关算法
    一、栈的基础概念1、栈的定义栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。栈顶(Top):线性表允许进行插入删除的那一端。栈底(Bottom):固定的,不允许进行插入和删除的另一端。空栈:不含任何元素的空表。栈又......
  • 单向循环链表的实现及相关算法
    1.单向循环链表特点:每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址),末尾节点的指针域指向了头节点1.1实现过程1.1.1、构建结点structNode{ Node(intvalue=0): val(value), next(nullptr) {} intval; Node*next;};1......
  • 大厂面试Java工程师为什么总爱问Spring相关问题?
    因为Spring框架自从诞生以来就一直备受开发者青睐,很多Java程序员实质上就是Spring程序员,它涵盖了Spring、Springboot、SpringCloud等诸多解决方案,一般我们都会统称为Spring全家桶!出于Spring框架在Java开发者心中中的统治地位,所以不管是面试还是工作,Spring都是绕不开的重点也是......
  • LTE 利用FFT 实现PSS的快速相关
    本期介绍一下怎么利用快速傅里叶变换来实现LTEPSS的快速相关。看下数字信号处理书本上线性卷积的数学表达式:假设h(n)和x(n)的长度分别为N和M,线性卷积的结果用yline(n)表示,则对比一下可以发现LTEPSS相关可以用线性卷积来实现,只需要把本地序列共轭翻转。我们知道用FFT方......
  • 宝塔后台解决宝塔相关问题
    针对宝塔后台使用过程中可能遇到的问题及其解决方案,可以总结如下:1.系统资源占用过高解决方案:优化宝塔面板的配置,减少不必要的服务运行。升级服务器硬件配置,如增加内存或CPU。定期清理无用的日志文件和缓存。2.面板无法正常开启解决方案:检查服务器防火墙设置,确保......
  • 关于软件开发中UI相关的问题
    因为个人的使用习惯,我现在经常是笔记本+显示器的使用方式。然后家里用的是27寸的4K显示器,显示器的缩放比例一般是设置成150%。使用的过程中发现很多的软件,在UI显示上都会出现一些问题。主要是两点:1、多屏/横竖屏。一些软件在有多个显示屏,特别是几个显示屏的分辨率不一样,或者有横......
  • keycloak~token配置相关说明
    会话有效期在Keycloak中,"SSOSessionIdle"和"SSOSessionMax"是用于配置单点登录(SSO)会话的两个参数。这两个参数影响用户在系统中的会话过期和最大有效时间。SSOSessionIdle(单点登录会话空闲时间):定义:表示用户在系统中没有活动的时间阈值。如果用户在这段时间内没......
  • 相关文章整理记录
    C3:Cross-instanceguidedContrastiveClusteringhttps://arxiv.org/pdf/2211.07136v4提出了一种新颖的对比聚类方法,跨实例引导的对比聚类(C3),它考虑了跨样本关系以增加正对的数量,并减轻假负、噪声和异常样本对数据学习表示的影响。特别是,我们定义了一个新的损失函数,该函数使......
  • Java相关面试题(2024大厂高频面试题系列)
    一、多线程基础基础知识1.并发编程1.1并发编程的优缺点优点:充分利用多核CPU的计算能力,通过并发编程的形式将多核CPU的计算能力发挥到极致,性能得到提升。方面进行业务的拆分。提高系统并发能力和性能:高并发系统的开发,并发编程会显得尤为重要,利用好多线程机制可以大大提高......
  • 线性基相关模板
    [ABC236F]Spices有\(2^N-1\)个数字,分别编号为\(1,2,\dots,2^N-1\),想获得编号为\(i\)的数字需要支付\(c_i\)的代价。现在你可以从这些数字中选出一些数,使得你可以通过你选择的某些数的编号的异或和来表示出\([1,2^N-1]\)中的所有数。请你求出最少需要......