贵州做网站公司
贵州做网站公司~专业!靠谱!
10年网站模板开发经验,熟悉国内外开源网站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等网站程序,可为您提供网站建设,网站克隆,仿站,网页设计,网站制作,网站推广优化等服务。我们专注高端营销型网站,企业官网,集团官网,自适应网站,手机网站,网络营销,网站优化,网站服务器环境搭建以及托管运维等。为客户提供一站式网站解决方案!!!

连通性

来源:网络转载 时间:2024-01-29 08:03:53

无向图的联通分量

割点:在一个联通分量里面有一些关键点,如果删除它,会把这个联通分量分为更多。 割边——双连通问题

有多少个割点:DFS,深搜优先生成树

对任意一个点s做DFS,生成一棵树

1)如果树的根节点s有两个或更多的孩子:s是割点

2)T的非根节点u是割点:当且仅当u存在一个子节点v,v及其后代都没有回退边连回u的祖先

HOW:u的直接后代v,数组num[]表示DFS时候的顺序,low[i]表示i及其后代能够回退回的祖先的num,一开始是num[i]=low[i]=dfn++

如果low[v]>=num[u],那么u就是割点

如果low[v]>num[u],那么u-->v就是割边

int low[maxn],num[maxn];vector<int> g[maxn];bool iscut[maxn];int dfn;void dfs(int u,int fa){low[u]=num[u]=dfn++;  //初始值为DFS访问的顺序int child=0;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!num[v]){child++;dfs(v,u);low[u]=min(low[u],low[v]);   //用后代的Low更新爸爸的lowif(low[v]>=num[u]&&u!=1) //判断割点1:不是根节点的判断 iscut[u]=1; }else if(num[v]<num[u]&&v!=fa){low[u]=min(low[u],num[v]); //处理回退边,fa也是u的邻居,但是之前已经访问过,所以不需要处理 }}if(u==1&&child>=2) iscut[1]=1; //根节点 }int main(){int ans,n;//输入图memset(low,0,sizeof(low));memset(num,0,sizeof(num));dfn=0;memset(iscut,0,sizeof(iscut));ans=0;dfs(1,-1);for(int i=1;i<=n;i++) ans+=iscut[i];cout<<ans<<endl;return 0;}

双连通分量:

在一个联通图中任选两点,如果至少存在两条“点不重复”的路径,成为点双连通,点双连通极大子图:点双连通分量(没有割点)

边双连通分量:没有割边

点双连通分量:Tarjan,在dfs的时候,把遍历过程中的点保存起来,就可以得到点双连通分量,保存在栈,找到割点就拿出来,注意存在栈的是边

边双连通分量:缩点的技术:

1)首先找出图G的所有边双连通分量,DFS时,所有点生成low值,low值相同的就是同一个SCC,,有多少个SCC就有多少个边双连通分量

2)把每个边双连通分量看作一个点,low值相同的合并为一个点

3)转化为一棵树,即至少在缩点树上面增加多少条边才能变为一个边双连通图,即(度为1的点+1)/2

下面的是求需要连接多少条边才能变为双连通分量,只需要low数组

#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<stack>#include<cstdio>#include<queue>#include<map>#include<vector>#include<set>using namespace std;const int maxn=1010;const int INF=0x3fffffff;typedef long long LL;int n,m,low[maxn],dfn;vector<int> g[maxn]; void dfs(int u,int fa){low[u]=++dfn;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v==fa) continue;if(!low[v]) dfs(v,u);low[u]=min(low[u],low[v]);}}int degree[maxn]; //计算每个缩点的度数 int tarjan(){memset(degree,0,sizeof(degree));for(int i=1;i<=n;i++){for(int j=0;j<g[i].size();j++){if(low[i]!=low[g[i][j]]){degree[low[i]]++;}}} int res=0;for(int i=1;i<=n;i++){if(degree[i]==1) res++;}return res;}int main(){while(~scanf("%d %d",&n,&m)){memset(low,0,sizeof(low));for(int i=0;i<=n;i++) g[i].clear();for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);g[a].push_back(b);g[b].push_back(a);}dfn=0;dfs(1,-1);int ans=tarjan();printf("%d\n",(ans+1)/2);}return 0;}

有向图的连通性

强连通:如果两个点:u,v是互相达到的

无向图:联通 有向图:强连通

图中有多少SCC:暴力O(V^2+E)

kosaraju算法O(V+E):反图

(1)有向图G,建立反图rG,不会改变连通性

(2)对原图G做DFS,标记点的先后顺序,递归在最底层的点标记最小,回退过程中,其他点的优先级加大

(3)在反图RG上做DFS,从优先级大的开始做

Tarjan算法O(V+E):用栈分离不同的SCC

最先入栈的点:是这个SCC的祖先,他的num[]=low[]

比上面要快些

#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<cstdio>#include<queue>#include<map>#include<vector>#include<set>using namespace std;const int maxn=10010;const int INF=0x3fffffff;typedef long long LL;int cnt=0,dfn=0;int low[maxn],num[maxn];int sccno[maxn],stack[maxn],top;vector<int> g[maxn];void dfs(int u){stack[top++]=u;low[u]=num[u]=++dfn;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!num[v]){dfs(v);low[u]=min(low[u],low[v]);}else if(!sccno[v]){  //处理回退边  low[u]=min(low[u],num[v]);}}if(low[u]==num[u]){  //栈底的点是SCC的祖先, cnt++;while(1){int v=stack[top--];sccno[v]=cnt;if(u==v) break; //到达了祖先 }} } void tarjan(int n){ cnt=top=dfn=0; memset(sccno,0,sizeof(sccno)); memset(num,0,sizeof(num)); memset(low,0,sizeof(low)); for(int i=1;i<=n;i++){ if(!num[i]) dfs(i); } }  int main(){int n,m,u,v;while(scanf("%d %d",&n,&m),n!=0||m!=0){for(int i=0;i<=n;i++){g[i].clear();}for(int i=0;i<m;i++){scanf("%d %d",&u,&v);g[u].push_back(v);}tarjan(n);if(cnt==1) printf("Yes\n");else printf("No\n");} return 0;}

  

标签:连通性-
上一篇:while循环语句
下一篇:回到顶部的方法

SEO小店网站优化 能带来大量精准流量的网站才是好网站,小店网络公司SEO优化推广可以为企业网站带来大量的有效流量。 ...

汉寿网站排名快速提升 汉寿网络公司快速提升企业网站排名,通过网站优化推广,让汉寿企业网站在搜索引擎的排名长期稳定。 ...

SEO张家界网站优化 能带来大量精准流量的网站才是好网站,张家界网络公司SEO优化推广可以为企业网站带来大量的有效流量。 ...

autocad如何画两条平行直线的中心线?绘制直线的第一个点时,用手按住Ctrl的同时单击鼠标右键,会弹出一个菜单,从中可以选择 "从两点的中点 ",依次点击两条平行线的端点得到中点,再画一次得到中心线。cad如何画曲线的平行线?具体操作步骤如下:需要准备的材料有:电脑,CAD。1.首先,打开CAD并点击 "偏移和左侧的图标选项。2.然后输入 "偏移和在这个页面的命令的右边。3.然后输入页面右侧两...

矿泉水瓶底部有个三角,里面有个“1”,是什么意思?矿泉水瓶底部有一个三角形,里面有一个1代表PET材料,三角形标志里面有一个数字,就是塑料回收标识。Pet是聚对苯二甲酸乙二酯。这种材料耐热70℃,易变形。一些有害物质会融化。常见于矿泉水瓶、碳酸饮料瓶等,当温度达到70℃时易变形,高温下不能盛酒、油等物质。因此,pet水瓶不能回收用来装热水。这种材料耐热70℃,仅适用于盛装热饮料或冷冻饮料。填充高温...

一个人静静听着光阴的故事,突然间泪流满面,70后的我真的老了吗?一个人静静地听着时光的故事,眼泪,真的老了吗?在我看来,如果你的心态不一定好,你就会永远年轻。每个人都失去了青春和岁月。以乐观的心态对待这个问题,对待生活中的每一天。虽然你老了,但你觉得自己像个还没长大的孩子。如果你想相信生命永远像彩虹,你会觉得年轻,你不会流泪。当你快乐地面对生活时,你仍然会过着美好的生活。如何评价杜子建学徒@波哥杂...

TOP