深夜敲模板_4——无向图的割顶和桥

/***
    dfs遍历一遍整个图,标出时间戳 dfs_clock,保存在pre[]里
    遍历后得到一个森林
    对于每一颗树,每个节点是割顶的情况:
        1:根:    有两个或两个以上的子节点
        2:非根:  对于节点u,low(u)表示u及u的所有节点的反向边所能连回的最早的节点的pre[]值
                   如果u的所有子节点的low[v]>=pre[u]; 那么u节点就是割顶
                   特别的,如果low[u]>pre[u],边(u,v)还是一个桥
    初始化是,假设所有的low(u)=u;即所有节点都能连回自己
***/
1:
int head[MAXN],pre[MAXN],low[MAXN],cnt,dfs_clock;
bool iscut[MAXN],isedgecut[MAXM];///true表示是割顶
struct Edge{
    int v;
    int next,to;
}edge[MAXM>>1];

void add(int u,int v){
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

void init(){
    cnt = dfs_clock = 0;
    memset(head,-1,sizeof(head));
    memset(pre,0,sizeof(pre));
}

void dfs(int u,int fa){
    low[u] = pre[u] = ++dfs_clock;
    int child = 0;
    *****int lowv  = dfs_clock+1;
    for(int i = head[u];i != -1;i = edge[i].next){
        int v = edge[u].to;
        if(!pre[v]){
            child++;
            dfs(v,u);
            *****lowv = min(lowv,low[v]);
            low[u] = min(low[u],low[v]);
            if(low[v] >= pre[u])    iscut[u] = true;///这个地方也可以改成vector,找的时候更快
            *****if(low[v] > pre[u])     isedgecut[i] = true;///找到的桥
        }
        else if(v != fa && pre[v] < pre[u]){
            low[u] = min(low[u],pre[v]);
        }
    }
    if(fa == -1 && child > 1)   iscut[u]=true;
    *****if(fa == -1 && lowv != u){
        for(int i = head[u];i != -1;i = edge[i].next)  isedgecut[i]=true;
    }
}

2:
vector <int> G[MAXN];
*****vector < pair<int,int> > edge;

void dfs(int u,int fa){
    low[u] = pre[u] = ++dfs_clock;
    int child = 0;
    *****int lowv  = dfs_clock+1;
    for(int i = 0;i < G[u].size();i++){
        int v = G[u][v];
        if(!pre[v]){
            child++;
            dfs(v,u);
            *****lowv = min(lowv,low[v]);
            low[u] = min(low[u],low[v]);
            if(low[v] >= pre[u])    iscut[u] = true;
            *****if(low[v] > pre[u])    edge.push_back(mak_pair(u,v));
        }
        else if(v != fa && pre[v] < pre[u]){
            low[u] = min(low[u],pre[v]);
        }
    }
    if(fa == -1 && child > 1)   iscut[u] = true;
    *****if(fa == -1 && lowv != u){
        for(int i = 0;i < G[u].size();i++)  edge.push_back(make_pair(u,v));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值