首页 > 其他分享 >图论

图论

时间:2023-11-02 17:34:59浏览次数:37  
标签:图论 一个点 int 割点 dfs num low

图论的基础算法暂且不提,这里直接引出一种难度比较中等的算法 \(—— Tarjan\)

这是 \(Tarjan\) 研发出的算法,复杂度通常为 \(\Theta(n)\).

图论中的 \(Tarjan\) 可以解决图的连通性问题,比如割点割边等\(.\)

先提出一些定义 \(/\) 符号 \(:\)

  1. 连通块 , 指一个任意两点互相可达的图
无向图的连通性
1. Tarjan 割点

割点,可以简单地理解为可以满足

删去该点之后整张图的连通块数量会因而增加

的任意一个点

求割点可以简单的用 dfs树 来解决,这也是 tanjan 算法的原理。

可以记录两个数组 \(dfn[N],low[N]\) 来分别记录点在树上出现的时间戳,以及记录点可以不通过树边回溯到的树上深度最小的点。

我们记 \(T(u)\) 为以 \(u\) 为根的子树。引入两个定理。

定理 1.1

对于一颗 \(dfs\) 树,如果这棵树的根节点的子节点(子树)数量大于 1,那么这个点是一个割点。原因显然。

定理 1.2

对于 \(dfs\) 树上的点 \(u\) ,去讨论 \(u\) 下的子树的每一个节点,如果不存在 \(\forall v\in T(u)\) 满足 \(low[v]<u\) ,及没有任何一个点可以回溯到点 \(u\) 上面的点就可以判断 \(u\) 是一个割点 \(.\)

可以尝试感性地理解这个定理 \(:\)

如果子树上的任意一个点可以回退到 \(u\) 上面的点,也就代表这个点可以不用经过点 \(u\) 联通到其他连通块,这个时候点 \(u\) 并不是相当重要的,也就是可以删除点 \(u.\) 所以一个非根点可以成为割点当且仅当它对于它的子树至关重要。


联立两个定理,就可以用 \(O(n)\) 的复杂度求得,其中 \(low\) 可以在回溯的时候迭代。

注意,因为每一个点的遍历次数都仅为 \(1\),所以无论这个图有多么毒瘤用这种方法求割点都是 \(\Theta(n)\) , 原因显然。

常数也较为恒定,是一种比较简单的求割点方法,注意要保证图上的每一个点都被均匀地遍历到,否则在图不连通的情况下会吃大亏。

细节上来说,在每一个点刚刚遍历到的时候其 \(low\) 值为它本身,因为该点至少能回退到自己。

模板题 \(:\)

\(\color{black}{P3388}\)

然后是一张丑陋的代码

#include <bits/stdc++.h>
#define FOR(i,s,n) for(register int i=s;i<=n;++i)
#define ROF(i,n,s) for(register int i=n;i>=s;--i)
#define ll long long
using namespace std;
const int N=2e4+5;
int low[N],num[N],tot,root;
bool iscut[N];
vector<int> G[N];

void dfs(int u,int rt){
	low[u]=num[u]=++tot;
	int child = 0;
	for(auto v:G[u]){
		if(!num[v]){
			if(v!=rt)++child;
			dfs(v,u);
			low[u]=min(low[v],low[u]);
			if(low[v]>=num[u] && u!=root)iscut[u]=true;
		}
		else if(num[v]<num[u] && v!=rt)
			low[u]=min(low[u],num[v]);
	}
	if(u==root && child>=2) iscut[root]=true;
}

int main(){
	int ans=0,n,m;
	cin>>n>>m;
	int a,b;
	FOR(i,1,m){
		cin>>a>>b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	FOR(i,1,n){
		root=i;
		dfs(i,i);
	}
	FOR(i,1,n){
		if(iscut[i])
			++ans;
	}
	cout<<ans<<endl;
	FOR(i,1,n){
		if(iscut[i])
			cout<<i<<' ';
	}
	return 0;
}

标签:图论,一个点,int,割点,dfs,num,low
From: https://www.cnblogs.com/qxblog/p/Graph.html

相关文章

  • USACO 图论题 - from Luogu
    题单记录:P2984[USACO10FEB]ChocolateGivingS这题直接按题意只有50pts,复杂度\(O(B~\cdotM\logN)\),显然超时,然后我就想啊想,发现从s->1->t跑两遍dij和1->s(t)跑一遍dij是等效的,没啥用......我居然还想了好久,才发现根本不需要每次都跑,跑一次预处理就行了..........
  • 提高组算法-图论学习笔记
    ##2023-10-21第一节基本概念      一、什么是图:点用边连起来就叫做图,是一种数据结构。二、图的一些定义和概念1、有向图:图的边有方向,只能按箭头方向从一点到另一点。  2、无向图:图的边没有方向,可以双向。3、结点的度:无向......
  • 【重学OI】图论大礼包
    继上次数学大礼包之后,再度推出图论出于一定的功利性以及必要,我们部分基本用不到的算法不会提到本篇没说题号默认就是洛谷有模板题本文尽可能略去证明,目的就是复习对于图的储存,我们不讲,代码里一般是用链式前向星(不会bilibili搜索不分解的AgOh)part0概念图:一张图\(G\)由若......
  • 图论
    1.树上简单路径树上简单路径\((u,v)\)的关键是LCA。具体而言,通过端点的LCA节点\(p\),可以将\((u,v)\)拆分为两条祖先-后代链\((u,p)\),\((v,p)\),利于处理。以下讨论的路径均为简单路径。1.1基础LCA若干种求法:暴力跳父亲倍增重链剖分通过dfs序转成RMQ......
  • 【图论】二分图的判定 学习笔记
    二分图的判定记无向图\(G=(V,E)\),若存在点集\(A,B\)满足:\(A\cupB=V\)\(A\capB=\varnothing\)\(\foralle=(u,v)\inE\),满足\(u,v\)不同时在\(A\)或\(B\)中。则称图\(G\)为二分图,\(A,B\)分别称作二分图的左部与右部。二分图的判定定理下面三......
  • 图论2
    Week10P1636Einstein学画画知识点:欧拉路存在欧拉路的条件:图是连通的,有且只有2个奇点。存在欧拉回路的条件:图是连通的,有0个奇点。思路:统计所有点的度数:如果是奇数结果加一;如果是偶数则是途中的点,最后结果除以二。注意:连成一串的点所有点的度都是偶数,但是可以一笔......
  • 图论
    Week9图论P5318【深基18.例3】查找文献思路:用vector存单向图,排序,深搜光搜注意:“如果有很多篇文章可以参阅,请先看编号较小的那篇”,需要排序(按终点由小到大排列,终点相同则起点有小到大#include<bits/stdc++.h>usingnamespacestd;structedge{ intu,v;};v......
  • 图论的一些知识
    tarjan算法虚树DAG剖分矩阵树定理最小树形图()斯坦纳树(感觉可以看看?)同余最短路平面图and对偶图线性规划网络流一般图最大匹配Prüfer序列竞赛图稳定婚姻问题2-sat仙人掌Dilworth定理()tarjan算法有向图\(\to\)强连通分量无向图\(\to\)广义圆方树......
  • 搜索与图论2.2-Floyd算法
    一、简述\(Floyd\)算法是一种可以快速求解图上所有顶点之间最短路径的算法。\(Bellman-Ford\)和\(Dijkstra\)算法求解的都是从一个起始点开始的最短路。如果想要求解图中所有顶点之间的最短路,就需要枚举每个点做为起点,这样十分低效。\(Floyd\)算法(也称\(Floyd-Warshall\)......
  • 图论总结
    图论树和图的存储`树是特殊的图,无环的联通图图分为有向图和无向图,无向图是一种特殊的有向图`邻接矩阵存稠密图,空间复杂度\(O(n^2)\)g[u][v]=w;邻接表voidinit(){ for(inti=0;i<N;i++) h[i]=-1;}voidadd(inta,intb){//在链表头插......