图的连通性以及割点

2024-02-18 01:38
文章标签 连通性 割点

本文主要是介绍图的连通性以及割点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先明白几个定理:

  • 连通分量:无向图 G 的一个极大连通子图称为 G 的一个连通分量(或连通分支)。连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量。
  • 强连通图:有向图 G=(V,E) 中,若对于V中任意两个不同的顶点 x 和 y ,都存在从x 到 y 以及从 y 到 x 的路径,则称 G 是强连通图(Strongly Connected Graph)。相应地有强连通分量(Strongly Connected Component)的概念。强连通图只有一个强连通分量,即是其自身;非强连通的有向图有多个强连通分量

1. 判断无向图的连通性。

   用bfs或者dfs,遍历,如果能遍历完所有结点,则是连通图。

  比如,要求无向图的割点的集合,最容易想到的方法就是依次测试每个结点判断其对图连通性的影响。

  有更简单的方法。


2. 有向图的单连通性。对于任意的两个点,i,j,存在i到j或者j到i的路径

  1. 最容易想到的算法是floyd算法。

      floyd算法本来用以求图中任意两点间的最短路径,大体思路是:

     依次以每个点k作为i--->j的中间节点,求d(i,j) = min(d(i,j),d(i,k)+d(k,j))

    如果用floyd算法判断任意两个点的连通性?

    可以直接用上面的算法,但是可以将加法和min操作转为位运算。

    d(i,j) = d(i,j) | (d(i,k) & d(k,j))

 2. 上面的算法时间复杂度是O(n^3)

     http://hi.baidu.com/735612658gfy/item/e2e8c8d3362fa9f2b3f7777b

   

思路:判断一个有向图是不是强连通的可以直接用tarjan算法。

          但是判断是不是单向联通的就麻烦了。

          开始我想用floyd,后来又想到了一条路一条路的找,但是这两种方法的复杂度太高。

正解:对于一个DAG图,若是单向联通的我们可以有这么一个性质,就是存在一条路,这条路可以经过图中的每一个点。下面证明一下。

我们从图中选择一个入度为0的点a,和一个出度为0的点b,则剩下的点肯定都满足在a,b之间。

不妨找一点k ,则a~k~b,剩下的点也肯定在两个~之间的一个,以此类推。

我们先让这张图变成DAG,我们用tarjan算法缩点,这张图就变成了一个DAG图。


#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
stack<int>s;
struct hh{int u,v,next;}tp[6005],map[6006];int head[1050],mhead[1050],num,mnum,low[1050],lp[1050],now,f[1050];bool in[1050];int n,m,step,total;void add(int a,int b){tp[num].u=a;tp[num].v=b;tp[num].next=head[a]; head[a]=num++;}void madd(int a,int b){map[mnum].u=a; map[mnum].v=b;map[mnum].next=mhead[a]; mhead[a]=mnum++;}void init(){int a,b;num=0; mnum=0;step=total=1;while(!s.empty()) s.pop();for(int i=1;i<=n;i++){in[i]=0;low[i]=lp[i]=f[i]=0;}memset(head,-1,sizeof(head));memset(mhead,-1,sizeof(mhead));scanf("%d%d",&n,&m);for(int i=0;i<m;i++){scanf("%d%d",&a,&b);add(a,b);}}void tarjan(int u){int v;low[u]=lp[u]=step++;s.push(u); in[u]=1;for(int i=head[u];i!=-1;i=tp[i].next){v=tp[i].v;if(!low[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(in[v]){low[u]=min(low[u],lp[v]);}}if(low[u]==lp[u]){int haha;while(1){haha=s.top(); s.pop();f[haha]=total; in[haha]=0;if(haha==u)break;}total++;}}void suodian(){for(int i=0;i<num;i++){if(f[tp[i].u]!=f[tp[i].v])madd(f[tp[i].u],f[tp[i].v]);}}bool can[1004][1004];int b[1050];bool  dfs(int u,int now){in[u]=1;if(now==total-1)return true;bool flag=0;for(int i=mhead[u];i!=-1;i=map[i].next){flag=dfs(map[i].v,now+1);if(flag)return true;}return false ;}void result(){memset(in,0,sizeof(in));for(int i=1;i<=n;i++){if(!in[i]){bool flag=dfs(i,1);{if(flag){cout<<"Yes"<<endl; return ;}}}}cout<<"No"<<endl;}int main(){int t;scanf("%d",&t);while(t--){init();for(int i=1;i<=n;i++)if(!low[i])tarjan(i);suodian();//重新建图result();}}

也可以用上面的算法求出有向图的单连通分支, 对入度为0点,递归搜寻各向前通路至每一不可再前行点时,可对应得出一单项连通分支






这篇关于图的连通性以及割点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/719647

相关文章

图的割点、割线问题

图的割点问题 邻接矩阵表示图 package com.hyl.algorithm.other;import java.util.Arrays;import com.hyl.algorithm.search.base.SearchIntf;import com.hyl.algorithm.search.base.SearchIntfFactory;/*** 寻找图的割点* <p>** @aut

nc -s网络连通性测试

例如: nc -s 192.168.82.67 192.168.82.66 22 在这个命令中,您使用了nc(Netcat)工具来进行网络连接。下面是命令的详细说明: nc: 表示使用Netcat工具进行操作。-s 192.168.82.67: 指定源IP地址为192.168.82.67。这个参数让Netcat使用指定的IP地址进行网络连接,而不是默认的地址。192.168.82.66:

HIHO #1190 : 连通性·四(点的双联通分量)

题目链接 点的双联通分量,不注意写出了一个bug,找了2个多小时= =,我的边存的是0开始的,然后ans数组一开始也是0,然后就是if的地方。。。。。 还是tarjan的算法,结合提示,这里需要存边,然后栈里面保存的是边,而不是点,这里我用边在边集es中的编号,作为边的标志 #include<bits/stdc++.h>using namespace std;#define cl(a,b

HIHO #1185 : 连通性·三

题目链接 先使用tarjan算法,计算强连通分量,进行缩点成DAG,然后在使用拓扑排序计算 tarjan中,我们只需要从1号节点计算,因为开始时在1号点。 建立新图的过程中,1号点不能到达的点也不用建立到新图里面 #include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#defin

HIHO #1184 : 连通性二·边的双连通分量

题目链接 Tarjan算法,介绍可以看题目讲解,很好很清楚 无向图边的双联通分量的定义:对于一个无向图的子图,当删除其中任意一条边后,不改变图内点的连通性,这样的子图叫做边的双连通子图。而当子图的边数达到最大时,叫做边的双连通分量。 或者说,对于一个连通图,如果任意两点至少存在两条”边不重复”的路径。也就是要去每条边至少在一个简单的环中,也就是说所有的边都不是桥 同样是2个方法: 1)题

HIHO #1183 : 连通性一·割边与割点

题目链接 使用Tarjan算法计算无向图的割点和桥,提示讲解的也很清晰 需要注意的是,某一个割点可能会被多次计算,所以一般是先记录然后最后统一输出 1)按照题目的伪代码直接实现 2)稍微优化一下的,省一些空间 #include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define

P3388 【模板】割点(割顶)

~~~~~      P3388 【模板】割点(割顶) ~~~~~      总题单链接 割点的定义 ~~~~~      在一张无向图中,若删除一个点后连通块的数量会增加,那这个点就是割点。 怎么找割点 ~~~~~      按 d f s dfs dfs序 访问图上的每个点,每个点只访问一遍。 ~~~~~      先来看看时间戳的定义,若一个点的时间戳为 x x x,那

poj 1144 Network(割点)

http://poj.org/problem?id=1144 题意很简单,已知图中各边的连接情况,求割点的个数。 注意输入格式。。 #include<stdio.h>#include<vector>#include<string.h>#include<algorithm>using namespace std;vector<int> edge[110];int dfn[110]

运维的利器–监控–zabbix–第三步:配置zabbix–网络–原理:通过ping实现网络连通性监控

文章目录 通过ping实现网络连通性监控1、参数说明2、建立监控项3、创建图形 通过ping实现网络连通性监控 1、参数说明 ICMPPING[,,,,]通过ICMP ping检查主机是否可以访问。 target-目标IP或者域名 packets-数据包数量 interval-间隔时间(毫秒) size-数据包大小(字节) timeout超出时间(毫秒) ICMPPINGLO

springboot 搭建一个 测试Kafka 集群连通性demo

废话不多说直接上代码: 1.pom <!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka --><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><ver