目录

1.边连通分量

1.冗余路径

2.点连通分量

1.电力

2.矿场搭建


1.边连通分量

边连通分量(e-DCC): 就是删除无向图的一条边,假如该图不连通了,则这条边叫做桥,边连通分量就是极大的不含桥的连通分量

1.弄连个时间戳dfn表示第一次遍历到这个点的时间戳,low是他的子树中的最小的时间戳

2.假如是桥,则dfn[x]<low[y],则说明x->y这条边就是桥

3.用stack存边连通分量,因为假如low[x]==dfn[x],说明找到了这个点的祖宗节点,则入栈的就是他的子树,也就是边连通分量

1.冗余路径

395. 冗余路径 - AcWing题库

题目大意就是:给定一个无向连通图,问最少加多少条边,使得该图变成一个边双连通分量

先做一遍边的双连通分量,然后缩点建图,变成一棵树,答案就叶节点(也即度数为1的点)的一半向上取整,则ans=[cnt+1]/2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5010,M=20010;
int n,m;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],timestamp;
int stk[N],top;
int id[N],dcc_cnt;
bool is_bridge[M];
int d[N];
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u, int from)//u是当前节点,from是从那个节点更新过来的
{dfn[u]=low[u]=++timestamp;//第一次遍历让她们都等于时间戳stk[++top]=u;//把这个点入栈for(int i=h[u];~i;i=ne[i]){int j=e[i];if(!dfn[j])//假如没有遍历过{tarjan(j,i);//遍历一遍low[u]=min(low[u],low[j]);if(dfn[u]<low[j])//假如是桥is_bridge[i]=is_bridge[i^1]=true;//正向边和反向边都是标记为桥,反向边就是i^1}else if(i!=(from^1)) low[u]=min(low[u],dfn[j]);//假如正向边不等于转移过来的边,也即不是父节点,则更新}if(dfn[u]==low[u])//假如相等了说明找到了一个连通块{++dcc_cnt;//连通块++int y;do{y=stk[top--];//栈里的元素就是他的连通块元素id[y]=dcc_cnt;//标记这个点是属于这个连通块的}while(y!=u);}
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b;cin>>a>>b;add(a,b),add(b,a);}tarjan(1,-1);//搜索一下所有的边for(int i=0;i<idx;i++)//枚举一下所有的边if(is_bridge[i])//假如这条边是桥d[id[e[i]]]++;//则则这条边的上一个边连通分量度数++int cnt=0;for(int i=1;i<=dcc_cnt;i++)//缩点后的图if(d[i]==1) cnt++;//算一遍度数为1的边cout<<(cnt+1)/2<<endl;return 0;
}

2.点连通分量

点连通分量(v-DCC):就是删除无向图的一个点,假如该图不连通了,则这个点叫做割点,点连通分量就是极大的不含割点的连通分量

1.弄连个时间戳dfn表示第一次遍历到这个点的时间戳,low是他的子树中的最小的时间戳

2.求割点:当low[y]>=dfn[x],

(1)假如x不是根节点,那么x是割点

(2)假如是根节点,至少有两个字节点yi使得low[yi]>=dfn[x],则x是割点

3.用stack存边连通分量,因为假如low[x]==dfn[x],说明找到了这个点的祖宗节点,则入栈的就是他的子树,也就是边连通分量

1.电力

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

1.统计连通块的个数cnt

2.枚举从那个连通块中删,在枚举连通块中删除那个点,假如删除这个点后该连通块变成了s个,则答案就是max(s+cnt-1)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10010,M=30010;
int n,m,ans,root;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],timestamp;
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u)
{dfn[u]=low[u]=++timestamp;//第一次遍历让她们都等于时间戳int cnt=0;//记录删除割点后的连通块个数for(int i=h[u];~i;i=ne[i]){int j=e[i];if(!dfn[j])//假如没有遍历过{tarjan(j);//遍历一遍low[u]=min(low[u],low[j]);if(low[j]>=dfn[u]) cnt++;//假如是割点,则连通块++}else  low[u]=min(low[u],dfn[j]);//更新一遍最小值}if(u!=root&&cnt) cnt++;//假如不是根,且连通块个数不为0,说明这个也是一个割点,则连通块个数+1ans=max(ans,cnt);//更新一遍最大值
}
int main()
{while(scanf("%d%d",&n,&m),n||m){memset(dfn,0,sizeof dfn);//清空,因为dfn兼具判重的作用memset(h,-1,sizeof h);//清空idx=timestamp=0;//清空状态while(m--){int a,b;scanf("%d%d",&a,&b);add(a,b),add(b,a);}ans=0;int cnt=0;for(root=0;root<n;root++)//枚举每个为根if(!dfn[root])//假如不在任何一个连通块中{cnt++;//则新开个连通块tarjan(root);//遍历一遍}printf("%d\n",cnt+ans-1);}return 0;
}

2.矿场搭建

396. 矿场搭建 - AcWing题库

题意:给定一个无向图,问最少在几个点上设置出口,可以使得不管哪个点坍塌,其余所有点都可以与某个出口连通

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1010,M=510;
int n,m,root;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],timestamp;
int stk[N],top;
int id[N],dcc_cnt;
vector<int>dcc[N];
bool cut[N];
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u)
{dfn[u]=low[u]=++timestamp;//第一次遍历让她们都等于时间戳stk[++top]=u;if(u==root&&h[u]==-1)//假如是孤立点{dcc_cnt++;dcc[dcc_cnt].push_back(u);return;}int cnt=0;//记录子树的个数for(int i=h[u];~i;i=ne[i]){int j=e[i];if(!dfn[j])//假如没有遍历过{tarjan(j);//遍历一遍low[u]=min(low[u],low[j]);if(low[j]>=dfn[u]){cnt++;//子树加1if(u!=root||cnt>1) cut[u]=true;//假如不为根或者子树为>1则为割点++dcc_cnt;int y;//求割点中的点,也即点连通块的点,并放进队列中去do{y=stk[top--];dcc[dcc_cnt].push_back(y);}while(y!=j);dcc[dcc_cnt].push_back(u);}}else  low[u]=min(low[u],dfn[j]);//更新一遍最小值}
}
int main()
{int T=1;while(cin>>m,m){for(int i=1;i<=dcc_cnt;i++) dcc[i].clear();//清空idx=n=timestamp=top=dcc_cnt=0;//初始化memset(cut,0,sizeof cut);//清空割点memset(dfn,0,sizeof dfn);//清空,因为dfn兼具判重的作用memset(h,-1,sizeof h);//清空while(m--){int a,b;scanf("%d%d",&a,&b);n=max(n,max(a,b));add(a,b),add(b,a);}for(root=1;root<=n;root++)//枚举每个为根if(!dfn[root])//假如不在任何一个连通块中tarjan(root);//遍历一遍int res=0;ull num=1;for(int i=1;i<=dcc_cnt;i++)//枚举每一个连通块{int cnt=0;int len=dcc[i].size();for(int j=0;j<len;j++)//枚举该连通块的点if(cut[dcc[i][j]])//假如是割点,则割点++cnt++;if(cnt==0&&len>1) res+=2,num*=len*(len-1)/2;//假如不是割点且点的数量大于1else if(cnt==0) res++;//假如不是割点点的数量为1,则为孤立点else if(cnt==1) res++,num*=len-1;//假如有一个割点}printf("Case %d: %d %llu\n",T++,res,num);}return 0;
}

无向图双连通分量(DCC)相关推荐

  1. 图论学习-无向图双连通分量

    文章目录 无向图双连通分量 1.基本术语与概念 1.1.割点 1.2.桥 1.3.边双连通分量 (e-DCC) 1.4 点双连通分量 (v-DCC) 1.5 时间戳 2.求解 2.1 边双连通分量 2 ...

  2. 无向图——双连通分量

    双连通图:在无向图连通图中,如果删除该图中的任意一点和依附它的边,不改变图的连通性,则称该图为双连通的无向图. 由上述定义可知,双连通分量中,每两个结点之间至少有两条不同的路径可以相互到达. 割点:在 ...

  3. 无向图双连通分量BCC(全网最好理解)

    不是标题党,之前我也写过一篇比较全的,但是对于初学者不友好.传送门? 双连通分量(Biconnected component):     1.边双联通 E-BCC     2.点双连通 V-BCC 双 ...

  4. Tarjan的求双连通分量算法

    哎~气死我了!昨天晚上都写好了--一不小心把网页关了,写的全没了--MD 什么是双连通分量DCC(Double connected component)? 首先说一下一个无向连通图,若去掉任一点或任一 ...

  5. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...

  6. 有向图的强连通分量与无向图的双连通分量总结

    首先我们需要搞懂图论中的一些基础概念 完全图: 假设一个图有 n n n 个顶点, 并且每两个点之间都有边就叫完全图 连通图(多指无向图): 对于两个点, u , v , u,v, u,v, 如果 u ...

  7. 【图论专题】无向图的双连通分量

    A.AcWing 395. 冗余路径 结论:变成边双连通分量所需要新建的边数 无向图 连多少条边使得整个无向图变成任意两个点之间都有两条完全不相同的路径. 结论1:任意两个点之间都有两条完全不相同的路 ...

  8. 学习有向图和无向图的强连通分量(基本概念+割点+点双联通分量+桥+边双连通分量+全套模板【Tarjan】)

    最近总是考到Tarjan,让我措手不及 基本概念 割点以及点双连通分量 Tarjan法求割点 推导过程 代码实现 Tarjan法求点双连通分量 推导过程 代码实现 有向图的Tarjan缩点 桥与边双连 ...

  9. POJ 3352 无向图边双连通分量,缩点,无重边

    为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612.当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到.虽然比赛的时候最后水过了,但是那个模版看的还是一知半解 ...

最新文章

  1. 通过 JS 脚本去除csdn广告
  2. 编写一个函数,实现两个字符串的连接功能
  3. 坦克大战java_java版坦克大战游戏源码
  4. css选择器 nth-child
  5. python性能测试模块_python模块介绍- multi-mechanize 通用的性能测试工具
  6. 使用mysqld --install命令时出现MSVCR120.dll文件丢失错误
  7. hibernate框架学习笔记11:Criteria查询详解
  8. c语言怎么产生随机字母,菜鸟求助,写一个随机输出26个英文字母的程序
  9. 机器学习术语中英对照表
  10. 获取spring 框架源码方式
  11. 超级详细的iptables介绍
  12. 记录阿里技术面试全流程
  13. 塔望食业洞察|人参饮料行业环境 市场现状及发展思考
  14. 关于UI设计学习,推荐6个高质量的学习网站!
  15. 调用阿里云web API实现滑块验证码
  16. Linux下服务器基本环境搭建步骤详解(三种软件安装方式)
  17. mysql 批量插入数据方法_mysql大批量插入数据的4种方法示例
  18. 小米手机开发版、稳定版刷机和root等操作
  19. JL杰理AC692X(AC692N)蓝牙自定义配对密码
  20. 计算机挂载磁盘阵列,电脑中进行磁盘阵列RAID配置的详细步骤

热门文章

  1. 《文明之光 第二册》一一10.8 海上马车夫—— 荷兰的崛起(3)
  2. 0粉丝也能做短视频赚钱,每天稳定200多,居然还有人不知道
  3. jquery 立体走马灯_jquery无缝隙连续滚动代码【走马灯效果】
  4. 汉(海)明码 | “十六宫格法” 破解汉(海)明码相关题目(附软考经典例题)
  5. 迅雷卸载后,右键出现迅雷影音问题
  6. 唯有爱和勇气不可辜负 《无双争霸战》删档计费测试明日开启
  7. 20221电赛A题-适用MSP432E4系列的FFT速成
  8. ARM汇编压栈出栈具体详解
  9. JSW TOKEN 创建
  10. C语言怎么解决闪退问题