• Light OJ


       原题链接

        无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。

      也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点;然后再把所有点遍历一遍, 看其low和dfn,满足dfn[ fa ]<low[ i ](0<i<=n, i 的 father为fa) —— 则桥为fa-i。 找桥的时候,要注意看有没有重边;有重边,则不是桥。

      另外,本题的题意及测试样例中没有重边,所以不用考虑重边。

      


    带详细注释的题解:

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<algorithm>
    #include<stack>
    #include<vector>
    #define maxn 10010
    using namespace std;
    int dfn[maxn],low_link[maxn] ,Father[maxn];
    //tarjan 算法的dfn ——在DFS过程中 的访问序号(也可以叫做开始时间
    //tarjan 算法的low_link[i]——从i节点出发DFS过程中i下方节点所能到达的最早的节点的 开始时间
    int bridgenum, Time ,n ;  //桥的总数,dfn时间戳,n为顶点数,
    vector<int>G[maxn]; //定义图的邻接矩阵表
    stack<int>st;
    struct node{
        int u,v;
    }bridge[maxn];  //整个图的桥的存储
    bool cmp( node a,node b )
    {
        if(a.u!=b.u)return a.u<b.u;
        else return a.v<b.v;
    }
    void init(){
        int i;
        for(i=0;i<=n;i++)  //初始化邻接表
            G[i].clear();
        bridgenum=0;Time=0;
        memset(dfn,0,sizeof(dfn));
        memset(low_link,0,sizeof(low_link));
        memset(Father,0,sizeof(Father));
    }
    void tarjan(int u,int fa)
    {
        low_link[u]=dfn[u]=++Time;
        Father[u]=fa; //记录父节点
       // st.push(u);
        for(int i=0;i<(int)G[u].size();i++){
            int v=G[u][i];
            if(!dfn[v]){
                tarjan(v,u);
                low_link[u]=min(low_link[u],low_link[v]);
            }
            else if(v!=fa){  //不能连接到父节点!
                low_link[u]=min(low_link[u],dfn[v]);
            }
            else{
                //这种情况就是有重边的情况!不予处理,直接跳过!
            }
        }
    }
    void solve()
    {
        for(int i=0;i<n;i++){
            if(!dfn[i])
                tarjan(i,-1);
        }
        int ans=0;
        for(int i=0;i<n;i++){
            int v=Father[i];
            if(dfn[v]<low_link[i]&&v!=-1){  //若v-i可以构成父节点
                bridge[ans].u=v; //桥的两条边
                bridge[ans].v=i;
                if(bridge[ans].u>bridge[ans].v)
                    swap(bridge[ans].u,bridge[ans].v);
                ans++;
            }
        }
        sort(bridge,bridge+ans,cmp);
        printf("%d critical links
    ",ans);
        for(int i=0;i<ans;i++){
            printf("%d - %d
    ",bridge[i].u,bridge[i].v);
        }
    }
    int cal_num(char ch[]){
        int len=strlen(ch),s=0;
        for(int i=1;i<=len-2;i++){
            s=s*10+ch[i]-'0';
        }
        return s;
    }
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--)
        {
            init();
            char ch[10];
            int m ,u,v; //边数
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d%s",&u,ch);
                m=cal_num(ch);  //截取出数字存入m——边数
                for(int j=1;j<=m;j++){
                    scanf("%d",&v);
                    G[u].push_back(v);  //这里按单向边任意一边存储就可以了,毕竟是无向图!
                    G[v].push_back(u);
                }
            }
            printf("Case %d:
    ",++cas);
            solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HDU 5273 区间DP
    【管理心得之八】通过现象看本质,小王和小张谁更胜任?
    【Unity 3D】学习笔记四十二:粒子特效
    linux kernel的cmdline參数解析原理分析
    adoquery.refresh和adoquery.query的区别
    Delphi中的Sender:TObject对象解析
    ADODataSet与ADOQuery的区别
    visual studio 和 sql server 的激活密钥序列号
    修改VCL源码实现自定义输入对话框
    WINFORM 多条件动态查询 通用代码的设计与实现
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/8393391.html
Copyright © 2020-2023  润新知