前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tarjan求桥、割顶

tarjan求桥、割顶

作者头像
饶文津
发布2020-06-02 15:51:42
3320
发布2020-06-02 15:51:42
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏

若low[v]>dfn[u],则(u,v)为割边。但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理。我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v]。这样如果遍历完v的所有子节点后,发现low[v]=dfn[v],说明u的父亲边(u,v)为割边。

代码语言:javascript
复制
 1 void tarjan(int x)
 2 {
 3  vis[x]=1;
 4  dfn[x]=low[x]=++num;
 5  for(int i=head[x];i;i=next[i])
 6   if(!vis[ver[i]])
 7   {
 8    p[ver[i]]=edge[i];//记录父亲边
 9    tarjan(ver[i]);
10    low[x]=min(low[x],low[ver[i]]);
11   }
12   else if(p[x]!=edge[i])//不是父亲边才更新
13    low[x]=min(low[x],dfn[ver[i]]);
14  if(p[x]&&low[x]==dfn[x]) f[p[x]]=1;//是割边
15 }

求桥和割点的模板:

代码语言:javascript
复制
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<vector>
#define N 201
vector<int>G[N];
int n,m,low[N],dfn[N];
bool is_cut[N];
int father[N];
int tim=0;
void input()
{
    scanf("%d%d",&n,&m);
    int a,b;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&a,&b);
        G[a].push_back(b);/*邻接表储存无向边*/
        G[b].push_back(a);
    }
}
void Tarjan(int i,int Father)
{
    father[i]=Father;/*记录每一个点的父亲*/
    dfn[i]=low[i]=tim++;
    for(int j=0;j<G[i].size();++j)
    {
        int k=G[i][j];
        if(dfn[k]==-1)
        {
            Tarjan(k,i);
            low[i]=min(low[i],low[k]);
        }
        else if(Father!=k)/*假如k是i的父亲的话,那么这就是无向边中的重边,有重边那么一定不是桥*/
            low[i]=min(low[i],low[k]);
    }
}
void count()
{
    int rootson=0;
    Tarjan(1,0);
    for(int i=2;i<=n;++i)
    {
        int v=father[i];
        if(v==1)
        rootson++;/*统计根节点子树的个数,根节点的子树个数>=2,就是割点*/
        else{
            if(low[i]>=dfn[v])/*割点的条件*/
            is_cut[v]=true;
        }
    }
    if(rootson>1)
    is_cut[1]=true;
    for(int i=1;i<=n;++i)
    if(is_cut[i])
    printf("%d\n",i);
    for(int i=1;i<=n;++i)
    {
        int v=father[i];
        if(v>0&&low[i]>dfn[v])/*桥的条件*/
        printf("%d,%d\n",v,i);
    }
    
}
int main()
{
    input();
    memset(dfn,-1,sizeof(dfn));
    memset(father,0,sizeof(father));
    memset(low,-1,sizeof(low));
    memset(is_cut,false,sizeof(is_cut));
    count();
    return 0;
}

参考:poj3177-tarjan求桥/割边

tarjan算法--求无向图的割点和桥

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-08-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档