CSP-S 知识点复健 ---- 图论

引子:垃圾 f s y fsy fsy的图论比 f s y fsy fsy 还垃圾,于是来补一补


割点 x x x 是割点,当且仅当:

  1. x 是 d f s dfs dfs 树上的根结点且有两个以上的儿子
  2. l o w [ s o n ] ≥ d f n [ x ] low[son] \ge dfn[x] low[son]dfn[x]

因为大于等于说明能回到的最远点就是它
由于判断的是 l o w [ s o n ] ≥ d f n [ x ] low[son]\ge dfn[x] low[son]dfn[x],那么就不需要考虑父结点或重边的问题,从 x x x 出发的所有点的时间戳都可以用来更新 x x x

void dfs(int u){
   
   
	low[u] = dfn[u] = ++sign; int cnt = 0;
	for(int i = first[u]; i; i = nxt[i]){
   
   
		int t = to[i]; if(!dfn[t]){
   
   
			dfs(t), low[u] = min(low[u], low[t]);
			if(low[t] >= dfn[u]){
   
    ++cnt; if(u != rt || cnt > 1) cut[u] = 1;}
		}
		else low[u] = min(low[u], dfn[t]);
	}
}

割边 x x x 是割边,当且仅当:
l o w [ s o n ] > d f n [ x ] low[son] > dfn[x] low[son]>dfn[x]
然后不能回到父亲边,考虑重边的影响,需要记录来的边的编号

void dfs(int u, int from){
   
   
	low[u] = dfn[u] = ++sign;
	for(int i = first[u]; i; i = nxt[i]){
   
   
		int t = to[i]; if(!dfn[t]){
   
   
			dfs(t, i), low[u] = min(low[u], low[t]);
			if(low[t] > dfn[u]) bridge[i >> 1] = true;
		}
		else if(i != (from ^ 1)) low[u] = min(low[u], dfn[t]);
	}
}

边双联通分量:删去所有桥后每个联通块就是一个边双联通分量
边双的缩点:保留所有桥边,连接两端的边双联通


点双联通分量
定义:在一个无向图中,若任意两点间至少存在两条 “点不重复” 的路径,则说这个图是点双连通的
性质:

  1. 任意两点间至少存在两条点不重复的路径等价于图中删去任意一个点都不会改变图的连通性,
    即 BCC 中无割点
  2. 若BCC间有公共点,则公共点为原图的割点
  3. 无向连通图中割点一定属于至少两个BCC,非割点只属于一个BCC

求法:

  1. 当一个结点被第一次访问时,入栈
  2. d f n [ x ] ≤ l o w [ s o n ] dfn[x]\le low[son] dfn[x]low[son] 时,无论 x x x是不是跟,都要:
    弹栈直到 s o n son son 被弹出,弹出的所有点
    弹出的点与 x x x 构成点双联通分量
void dfs(int u){
   
   
	low[u] = dfn[u] = ++sign; sta[++top] = u;
	for(int i = first[u]; i; i = nxt[i]){
   
   
		int t = to[i]; 
		if(!dfn[t]){
   
   
			dfs(t); low[u] = min(low[u], low[t]);
			if(low[t] >= dfn[u]){
   
   
				++id; do{
   
    v[id].push_back(sta[top]); } while(sta[top--] != t);
				v[id].push_back(u);
			}
		} else low[u] = min(low[u], dfn[t]);
	}
}

点双联通的缩点
一个割点可能属于多个点双联通分量,缩完点后的点的个数等于割点数+点双连通分量个数
割点与包涵它的所有点双连边
连出来会是一棵树,可以求得无向图两点间的必经点:
树上两点路径上的割点


有向图的强连通分量
l o w [ x ] low[x] low[x] 为满足下列条件的最小时间戳:

  1. 在栈中
  2. 存在一条从 s u b t r e e ( x ) subtree(x) subtree(x) 出发的有向边以该点为终点

做法:

  1. 如果 y y y 没有访问过,那么 ( x , y ) (x,y) (x,y) 为树边,递归访问 y y y, 令 l o w [ x ] = m i n ( l o w [ x ] , l o w [ y ] ) low[x]=min(low[x],low[y]) low[x]=min(low[x],low[y
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FSYo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值