博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
割点、桥模板以及点双连通、边双连通
阅读量:7251 次
发布时间:2019-06-29

本文共 3642 字,大约阅读时间需要 12 分钟。

一、概念

概念:

1.桥: 如果在图G中删去一条边e后,图G的连通分支数增加,即W(G-e)>W(G),则称边u为G的桥,又称割边或关节边。

2.割点:如果在图G中删去一个结点u后,图G的连通分枝数增加,即W(G-u)>W(G),则称结点u为G的割点,又称关节点。

3.点双连通分量:不含割点的连通子图

4.边双连通分量:不含割边的连通子图

性质:

1.边双连通分量中,任意两点都在某个边环中。(任意两点不一定在点环中)

2.点双连通分量中,任意两点都在某个点环中。

3.点双连通分量不一定是边双连通分量,边双连通分量不一定是点双连通分量。

二、求桥模板

#define N 100100#define M 200110#define INF 0x3fffffffstruct node{    int from,to,next;}edge[2*M];vector
mat[N];//用来建新图.int n,m;int savex[M],savey[M];int cnt,pre[N];bool mark[2*M];bool save[2*M];int low[N];int mylink[N];void add_edge(int u,int v){ edge[cnt].to=v; edge[cnt].from=u; edge[cnt].next=pre[u]; pre[u]=cnt++;}void dfs(int s,int num)//寻找桥{ low[s] = num; int mi=num; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if(mark[p]==1) continue; if(low[v]==-1) { mark[p]=1; mark[p^1]=1; dfs(v,num+1); if(low[v]>num) // 说明edge[p]是桥 { save[p]=1; save[p^1]=1; } } mi=min(mi,low[v]); } low[s]=mi;}void dfs1(int s,int num)//缩点{ mylink[s]=num; mark[s]=1; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if(mark[v]==1||save[p]==1) continue; dfs1(v,num); }}void init(){ cnt=0; memset(pre,-1,sizeof(pre));}int main(){ init(); //构图 scanf("%d%d",&n,&m); for(int i=0;i

找到桥后,除去桥后的图中连通块即为边双连通分量。

 

三、割点模板

#define N 110#define M N*Nstruct node{    int to,next;}edge[2*M];int n;//图中节点个数,边的个数int pre[N],cnt;bool cutmark[N];int vis[N];int indx;int mylink[N];int tn;void init(){    memset(pre,-1,sizeof(pre));    cnt = 0;}void add_edge(int u,int v)//向图中插入一条无向边{    edge[cnt].to = v;    edge[cnt].next = pre[u];    pre[u] = cnt++;    edge[cnt].to = u;    edge[cnt].next = pre[v];    pre[v] = cnt++;}void build_map()//构图{    init();    //然后就是加边//    char str[10010];//    getchar();//    while(gets(str) && str[0]!='0')//    {//        stringstream in(str);//        int tmp;//        int tu=0;//        int flag=0;//        while(in>>tmp)//        {//            if(flag == 0)//            {//                flag = 1;//                tu = tmp;//            }//            else//            {//                add_edge(tu,tmp);//            }//        }//    }    }void dfs(int s,int fa,bool sign)//寻找割点{    vis[s] = ++indx;    int _mi = indx;//这个结点所能到达的最上层    int _cutedge = 0;    for (int p=pre[s]; p!=-1; p=edge[p].next) {        int _v = edge[p].to;        if(_v == fa) continue;        if(vis[_v] == -1)        {            dfs(_v,s,sign|1);            if(vis[_v] >= vis[s])            {                _cutedge ++;            }        }        _mi = min(_mi,vis[_v]);    }    vis[s] = _mi;    if( (sign == 0&&_cutedge>1)||(sign == 1&&_cutedge>0) )    {        cutmark[s] = 1;//为割点    }}void find_cutnode(){    memset(cutmark,0,sizeof(cutmark));    memset(vis,-1,sizeof(vis));    indx = 0;    for(int i=1;i<=n;i++)    {        if(vis[i] == -1)        {            dfs(i,-1,0);        }    }    //是否为割点,存在cutmark中}void dfs1(int s,int _id)//缩点用DFS{    mylink[s] = _id;    for(int p=pre[s];p!=-1;p=edge[p].next)    {        int _v = edge[p].to;        if(mylink[_v] == 0 && cutmark[_v] == 0)        {            dfs1(_v,_id);        }    }}void shuodian()//缩点,对应为[1-tn]中的点{    tn = 0;    memset(mylink,0,sizeof(mylink));    for(int i=1;i<=n;i++)    {        if(mylink[i] == 0 && cutmark[i] == 0)        {            dfs1(i,++tn);        }    }    //然后把割点也算成一个点双连通块    for(int i=1;i<=n;i++)    {        if(cutmark[i] == 1)        {            mylink[i] = ++tn;        }    }    //tn 表示点双连通块的个数.}

同理,除去割点后,剩余图中的连通块即为点双连通分量。

 

转载地址:http://lnhbm.baihongyu.com/

你可能感兴趣的文章
比特币钱包隔离认证开发指南
查看>>
《从0到1学习Flink》—— Data Sink 介绍
查看>>
Vue.js 渲染简写样式存在的问题
查看>>
cocos2d-x (js-binding)游戏开发解决方案设计稿
查看>>
改善Python程序的91个建议
查看>>
简单说说 angular.json 文件
查看>>
js-数据运算
查看>>
解决阿里云ECS运行前后台分离项目调用QQ互联导致: redirect uri is illegal(100010)问题...
查看>>
Slog48_项目上线之域名的备案
查看>>
[ 一起学React系列 -- 1 ] 信笔说JSX
查看>>
homebrew报错问题解决
查看>>
肉眼看到的相同两个字串的不同
查看>>
ng-zorror@~0.6升级@^1在开发中有哪些差异
查看>>
微信小程序 request请求封装
查看>>
Git 学习
查看>>
ES6深入浅出 模块系统
查看>>
一道js闭包面试题的学习
查看>>
微信小程序(新)必备知识
查看>>
网站接入微信扫码登录并获取用户基本信息(微信开放平台)
查看>>
HTC VIVE Wave 概览
查看>>