2019-07-29 17:50阅读: 661评论: 0推荐: 0

割点和桥

 

标题1

一、定义

  连通度(百度百科):

    割点集合:无向图中,删除集合中所有的点以及点所连接的边后,无向图不连通的集合

    割边集合:无向图中,删除集合中所有的边后,无向图不连通的集合

    点连通度:无向图中,割点集合中最小集合中的元素个数

    边连通度:无向图中,割边集合中的最小集合的元素个数

  双联通图,割点,和桥:

    双联通图:无向图中,边连通度或者点连通度大于1

    桥:图的边连通度为1,割边集合中的唯一元素集合中的元素为桥

    割点:图的点连通度为1,割点集合中的唯一元素集合中的元素为桥

  双联通分量

    在图G所有子图中,如果G'是双联通子图,G'不是任何一个双连通子图的真子集,则G'是一个极大双联通子图,特殊的点双联通分量又叫做

  

二、Tagan

  割点的条件:

    (满足一个即可)

    1.如果u树根,那么如果u的子树超过1,则u为割点

    2.如果u不为树根,且满足存在(u,v)为树枝边(u为v在搜索树中的父亲),并使得DFN(u)<=low(v)(删去u以及v以及v的子树不能到达u的祖先)

   

复制代码
#include<stdio.h>
#include<stdlib.h>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)

using namespace std;

const int N=100,M=200;
int n,m,num_edge,head[N+1],dfn[N+1],low[N+1],index;
bool cut[N+1];
struct Edge{
    int next,to;
}edge[2*M+2]; 
inline void Add_edge(int from,int to){
    edge[++num_edge]=(Edge){head[from],to},head[from]=num_edge;
}
inline int min(int fa,int fb){return fa<fb?fa:fb;}
void Tarjan(int x)
{
    low[x]=dfn[x]=++index;
    int cnt=0;
    for(int i=head[x];i;i=edge[i].next)
    {
        if(!dfn[edge[i].to])
        {
            cnt++;
            Tarjan(edge[i].to),low[x]=min(low[x],low[edge[i].to]);
            if(cnt>1&&x==1||dfn[x]<=low[edge[i].to])    cut[x]=1;
        }    
        else low[x]=min(low[x],dfn[edge[i].to]);
    }
}
int main()
{
    int from,to;
    scanf("%d%d",&n,&m);
    FORa(i,1,m)
    {
        scanf("%d%d",&from,&to);
        Add_edge(from,to),Add_edge(to,from);
    }
    Tarjan(1);
    FORa(i,1,n) printf("%d ",cut[i]);
    return 0;
}
/*7 8
1 5 
1 4
4 5
1 2
1 3
4 3
3 7
3 6*/
复制代码

  桥的条件:

    (满足一个即可)

    1.如果u树根,那么如果u的子树超过1,则u为割点

    2.如果u不为树根,且满足存在(u,v)为树枝边(u为v在搜索树中的父亲),并使得DFN(u)<=low(v)(删去u以及v以及v的子树不能到达u的祖先)

复制代码
#include<stdio.h>
#include<stdlib.h>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)

using namespace std;
const int N=1000,M=2000;
int n,m,num_edge=1,top,index,head[N+1],dfn[N+1],low[N+1],fa[N+1];
//注意num_edge是从奇数开始的,因为只有从奇数开始,第一个数就是偶数,那么偶数^1就是比它大1的奇数了 
bool bridge[M+1];
struct Edge{
    int next,to;
}edge[M+1];
inline void Add_edge(int from,int to)
{
    edge[++num_edge]=(Edge){head[from],to},head[from]=num_edge;
}
inline int min(int fa,int fb){return fa<fb?fa:fb;}
inline void Tarjan(int u)
{
    dfn[u]=low[u]=++index;
    for(int i=head[u],v;i;i=edge[i].next)
    {
        v=edge[i].to;
        if(i==(fa[u]^1)) continue;
        if(!dfn[v])
        {
            fa[v]=i,Tarjan(v);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]) bridge[fa[v]]=bridge[fa[v]^1]=1;
        }
        else low[u]=min(low[u],dfn[v]);                                         
    }
}
int main()
{
    int from,to;
    scanf("%d%d",&n,&m);
    FORa(i,1,m)
    {
        scanf("%d%d",&from,&to);
        Add_edge(from,to),Add_edge(to,from);
    }
    Tarjan(1);
    FORa(i,1,num_edge)
        if(bridge[i])
        {
            printf("%d",edge[i].to);
            printf(" %d\n",edge[i+1].to);
        }
    return 0;
}
/*12
16
12 11
11 8
11 10
8 10
10 9
9 8
9 7
7 6
5 7
6 5
6 4
6 3
4 3
2 3
3 2
4 1*/
复制代码

 

三、求双联通分量 

  点双联通分量:

     在求割点的时候,每一次找到树枝边和后向边,就将边加入到栈中,如果发现点u是割点,将栈中边(u,v)以上的边都弹出栈。这些边与边的点组成的图就是一个点强连通分量

  边双联同分量     

     在求桥的时候,求出桥(u,v)删去所有桥,剩下的连通块都是一个双联通分量,不包含桥

  将有桥的连通图变成双联通图:

     删去桥。将剩下的连通图缩成一个点,因为每一个连通图是一个边双联通分量,在边双联通图中加边不会减少桥的数目,所以先缩点

      我们可以看如果没有割边,根据树的性质,则将叶子结点连在一起就行,所以要连接的边数为(叶子结点+1)/2

    

 

 

本文作者:SeanOcean

本文链接:https://www.cnblogs.com/SeanOcean/p/11262387.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

大一ACMer蒟蒻一枚 坐标山大

欢迎你的到来(🤝);

posted @   SeanOcean  阅读(661)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

我和我的祖国 (童声版) - 李如意

词:张藜

曲:秦咏城

我和我的祖国

一刻也不能分割

无论我走到哪里

都流出一首赞歌

我歌唱每一座高山

我歌唱每一条河

袅袅炊烟 小小村落 路上一道辙

我最亲爱的祖国

我永远紧依着你的心窝

你用你那母亲的脉搏和我诉说

我的祖国和我

像海和浪花一朵

浪是那海的赤子

海是那浪的依托

每当大海在微笑

我就是笑的旋涡

我分担着海的忧愁

分享海的欢乐

我最亲爱的祖国

你是大海永不干涸

永远给我 碧浪清波 心中的歌

我最亲爱的祖国

你是大海永不干涸

永远给我 碧浪清波 心中的歌