• 无向图的连通性与相关问题


    无向图的连通性与相关问题

    一、相关概念:

    给定一张无向图(G=(V,E)):

    1、割点:若(xin V),从图中删去x以及与x相连的边后,图不连通,则x为割点。

    2、割边:若(ein E),从图中删去边e后,图不连通,则e为割边(桥)。

    3、点(边)双联通分量:一张图不存在割点(边),则此图为点(边)双连通分量。

    4、欧拉路、欧拉回路、欧拉图:若有一条从S到T的路径,满足恰好经过每一条边一次,则该路径为欧 拉路;特别地,当S=T时,此路为欧拉回路;一张所有点度数都为偶数的连通无向图为欧拉图。

    二、Tarjan与割边、割点:

    Tarjan能够在线性时间内求无向图的割点与割边。

    对于Tarjan算法中定义的相关数组与变量不在赘述,直接讲一下判定法则。

    割边判定法则:如果对于当前搜索点x,存在一条边(e=(x,y)),满足(low[y]>dfn[x]),则e为割边。

    code:

    void Tarjan(int x,int fx) {
    	RG int i,y;
    	dfn[x]=low[x]=++Time;
    	for(i=head[x];i;i=e[i].next)
    		if(!dfn[y=e[i].to]) {
    			Tarjan(y,x),low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x]) bri[i]=bri[i^1]=1;//成对储存,边从2开始
    		}
    		else if(y!=fx) low[x]=min(low[x],dfn[y]);
    }
    

    割边判定法则:如果对于当前搜索点x,满足(low[y]≥dfn[x]),则x是割点。

    ​ 不过,需要注意的是,当x为Tarjan算法的起点时,x至少需要有两个上述节点才是割点。

    void tarjan(int x) {
    	RG int i,k,y,num=0;
    	dfn[x]=low[x]=++Time;
    	for(i=head[x];i;i=e[i].next)
    		if(!dfn[y=e[i].to]) {
    			tarjan(y),low[x]=min(low[x],low[y]);
    			if(dfn[x]<=low[y]) 
    				if(x!=RT||++num>1) cut[x]=1;
    		}
    		else low[x]=min(low[x],dfn[y]);
    }
    

    三、Tarjan与双连通分量

    记点双连通分量为(v-DCC),边双连通分量为(e-DCC)

    (e-DCC) 求法:去掉图中的所有的割边,剩下的每一个连通块都是一个$e-DCC $(直接dfs即可)。

    (e-DCC) 缩点:直接把每一个连通块对应一个节点即可,可以得到一棵树(或森林)。

    void dfs(int x) {// 划分连通块
    	RG int i,y;
    	vis[x]=1,bel[x]=cnt;// 标记该点为所在e-DCC编号
    	for(i=head[x];i;i=e[i].next)
    		if(!vis[y=e[i].to]&&!bri[i]) dfs(y);
    }
    

    (v-DCC) 求法:不是直接去掉所有的割点,剩下的每一个连通块都是一个(v-DCC)

    ​ 因为一条割边只能在一个(e-DCC)中,但是一个割点去能在多个(v-DCC)中。

    ​ 所以可以用栈维护一下经过的节点,当存在(low[y]≥dfn[x])成立时,无论x是否为根,都弹栈到y为止

    ​ 所有这些弹出来的点与点x构成一个(v-DCC)

    (v-DCC) 缩点:每一个的(v-DCC)看成一个节点,同时每一个割点也单独看成一个节点。

    ​ 每一个(v-DCC)向它包含的每一个割点连边,得到一颗树。事实上这棵树很棒!(下方的链接随笔e.e.)

    ​ 割点的记录在新建的点上,其他点记录在对应的(v-DCC)上。

    for(i=1;i<=n;++i)
    	if(cut[i]) bel[i]=++cnt,mtx[cnt]=1;
    for(i=1,New();i<=cnt;++i)
    	for(j=0;j<vec[i].size();++j) // vec 存的是v-DCC的节点(含割点)
    		if(cut[x=vec[i][j]]) make(i,bel[x]);
    		else bel[x]=i;
    

    利用缩点,我们就可以进一步解决有关无向图必经边、必经点的问题!←想了解?←。

    四、欧拉路问题

    无解判定:当且仅当每个点的度都为偶数才存在欧拉回路。

    此处仅贴一下(dfs)求欧拉回路的模板(递归版):

    void dfs(int x) {
    	RG int i,y;
    	for(i=head[x];i;i=e[i].next) {
    		y=e[i].id;
    		if(!vis[y]) vis[y]=1,dfs(e[i].to),sta[++top]=y;
            // 将栈中的节点倒序输出就是一条具体的欧拉回路方案
    	}
    }
    
  • 相关阅读:
    学无止境,我爱python
    Flask目录
    Django目录
    前端目录
    python目录
    MySQL目录
    Oracle与Sql server的区别
    Git
    restful规范
    Django 解决跨域问题(写入到中间件中)
  • 原文地址:https://www.cnblogs.com/Bhllx/p/11265245.html
Copyright © 2020-2023  润新知