• Network---3694poj(桥与LCA)


    题目链接

    题意:

    有n个电脑1-n,m个连接,由于可能存在一些桥,如果这些桥出现了问题,那么会导致一些电脑之间无法连接,

     

    所以建立链接Q次,每次链接a和b电脑,求链接ab后还存在几个桥;

     

    如果说在ab之间建立连接, a和b的最近祖先(LCA),那么从a到LCA之间和b到LCA之间的桥都将不在是桥了

    这里找LCA根据dfn来往上一层一层的找;

    最近公共祖先LCA是指在一个树或者有向无环图中同时拥有 v 和 w 作为后代的最深的节点。在这里,我们定义一个节点也是其自己的后代,因此如果 v 是 w 的后代,那么 w 就是 v 和 w 的最近公共祖先。最近公共祖先是两个节点所有公共祖先中离根节点最远的,计算最近公共祖先和根节点的长度往往是有用的。比如为了计算树中两个节点v和w之间的距离,可以使用以方法:分别计算由v到根节点和w到根节点的距离,两者之和减去最近公共祖先到根节点的距离的两倍即可得到v到w的距离。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <cstring>
    using namespace std;
    #define INF 0xfffffff
    #define N 101000
    int low[N], dfn[N], f[N], bridge[N];
    //bridge[i] 是表示i和f[i]之间的路是否是桥;值为1的时候是桥;
    vector<vector<int> > G;
    int n, Time, m, nbridge;
    
    void Init()
    {
        G.clear();
        G.resize(n+1);
        Time = nbridge = 0;
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(f, 0, sizeof(f));
    }
    
    void Tarjan(int u, int father)
    {
        f[u] = father;
        dfn[u] = low[u] = ++Time;
        int len = G[u].size(), v;
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
            if(!dfn[v])
            {
                Tarjan(v, u);
                low[u] = min(low[u], low[v]);
    
                if(low[v] > dfn[u])
                {
                    bridge[v]++;
                    nbridge++;
                }
            }
            else if(v!=father)//避免找回自己的父节点;
                low[u] = min(low[u], dfn[v]);
        }
    }
    
    void LCA(int a, int b)
    {
        if( a == b )return ;
        ///因为dfn表示时间戳,所以a和b的最近公共祖先的时间戳一定小于等于a和b,所以我们要让dfn大的往上走;
        if(dfn[a] < dfn[b])
        {
            if(bridge[b]==1)
            {
                bridge[b] = 0;
                nbridge--;
            }
            LCA(a, f[b]);
        }
        else
        {
            if(bridge[a]==1)
            {
                bridge[a] = 0;
                nbridge--;
            }
            LCA(f[a], b);
        }
    }
    
    int main()
    {
        int t=0, a, b, Q;
        while(scanf("%d %d", &n, &m), n+m)
        {
            Init();
            while(m--)
            {
                scanf("%d %d", &a, &b);
                G[a].push_back(b);
                G[b].push_back(a);
            }
            Tarjan(1,0);
            printf("Case %d:
    ", ++t);
            scanf("%d", &Q);
            while(Q--)
            {
                scanf("%d%d", &a,&b);
                LCA(a,b);
                printf("%d
    ",nbridge);
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    mybatis中refid是什么意思
    spring源码之—Assert.notNull()
    MySQL数据库查询 concat 字段合并 身份证 名字手机号脱敏 case when等
    Java 8 引入的一个很有趣的特性是 Optional 类
    <if test="distinct">distinct </if> 这样写的问题
    bit类型数据,是1=false 还是0=false
    开发用的软件
    写代码的心得
    SQL Server数据库级别触发器
    python访问aws-S3服务
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4709732.html
Copyright © 2020-2023  润新知