• (连通图 模板题 无向图求割点)Network --UVA--315(POJ--1144)


    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=251

    http://poj.org/problem?id=1144

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82833#problem/B

    首先输入一个N(多实例,0结束),下面有不超过N行的数,每行的第一个数字代表后面的都和它存在边,0表示行输入的结束

    代码:

    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define maxn 10005
    
    int dfn[maxn];///代表最先遍历到这个点的时间
    int low[maxn];///这个点所能到达之前最早的时间点
    int Father[maxn];///保存这个节点的父亲节点
    int n, m, Time, top;///Time 时间点,  top用于栈操作
    vector<vector<int> > G;
    
    void Init()
    {
        G.clear();
        G.resize(n+1);
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(Father, 0, sizeof(Father));
        Time = 0;
    }
    
    void Tarjan(int u,int fa)
    {
        low[u] = dfn[u] = ++Time;
        Father[u] = fa;
        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]);
            }
            else if(fa != v)///假如我们在这里写上了 low[u] = min(low[v], low[u]),那么就相当于我们由v回到了v之前的节点
                low[u] = min(dfn[v], low[u]);
        }
    }
    void solve()
    {/**
    求割点
    一个顶点u是割点,当且仅当满足(1)或(2)
    (1) u为树根,且u有多于一个子树。
    (2) u不为树根,且满足存在(u,v)为树枝边(或称 父子边,即u为v在搜索树中的父亲),使得 dfn(u)<=low(v)。
    (也就是说 V 没办法绕过 u 点到达比 u dfn要小的点)
    注:这里所说的树是指,DFS下的搜索树*/
        int RootSon = 0, ans = 0;///根节点儿子的数量
        bool Cut[maxn] = {false};///标记数组,判断这个点是否是割点
    
        Tarjan(1,0);
    
        for(int i=2; i<=n; i++)
        {
            int v = Father[i];
            if(v == 1)///也是就说 i的父亲是根节点
                RootSon ++;
            else if(dfn[v] <= low[i])
                Cut[v] = true;
        }
    
        for(int i=2; i<=n; i++)
        {
            if(Cut[i])
                ans ++;
        }
        if(RootSon > 1)
            ans++;
    
        printf("%d
    ", ans);
    }
    int main()
    {
        while(scanf("%d", &n), n)
        {
            int a, b;
            char ch;
            Init();
            while(scanf("%d", &a), a)
            {
                while(scanf("%d%c",&b,&ch))
                {
                    G[a].push_back(b);
                    G[b].push_back(a);
                    if(ch == '
    ')
                        break;
                }
            }
            solve();
        }
        return 0;
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    
    #define N 105
    
    struct Edage
    {
        int v, next;
    } e[N*N];
    
    int n, m, Index, ans;
    int low[N], dfn[N], father[N], Head[N];
    
    void Init()
    {
        ans = Index = 0;
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(father, 0, sizeof(father));
        memset(Head, -1, sizeof(Head));
    }
    void Add(int u, int v)
    {
        e[ans].v = v;
        e[ans].next = Head[u];
        Head[u] = ans++;
    }
    void Tarjan(int u, int fa)
    {
        int v;
        low[u] = dfn[u] = ++Index;
        father[u] = fa;
    
        for(int j=Head[u]; j!=-1; j=e[j].next)
        {
            v = e[j].v;
            if(!dfn[v])
            {
                Tarjan(v, u);
                low[u] = min(low[u], low[v]);
            }
            else if(v!=fa)
                low[u] = min(low[u], dfn[v]);
        }
    }
    
    void Slove()
    {
        int sum=0, bnt=0;
        bool Cut[N]= {false};
    
        Tarjan(1, 0);
    
        for(int i=2; i<=n; i++)
        {
            int v = father[i];
            if(v==1)
                sum++;
            else if(dfn[v]<=low[i])
                Cut[v] = true;
        }
    
        for(int i=2; i<=n; i++)
        {
            if(Cut[i])
                bnt ++;
        }
    
        if(sum>1)
            bnt ++;
    
        printf("%d
    ", bnt);
    }
    
    
    int main()
    {
        while(scanf("%d", &n), n)
        {
            int u, v;
            char ch;
    
            Init();
            while(scanf("%d", &u), u)
            {
                while(1)
                {
                    scanf("%d%c", &v, &ch);
                    Add(u, v);
                    Add(v, u);
                    if(ch=='
    ')
                        break;
                }
            }
    
            Slove();
        }
        return 0;
    }
    勿忘初心
  • 相关阅读:
    转:高并发场景下强一致预算/库存扣减方案
    转:Dubbo性能调优参数及原理
    转:java线程状态说明,Jstack线程状态BLOCKED/TIMED_WAITING/WAITING解释
    使用增强学习法之SQ3R主动阅读
    建立实用投资计划
    使用smarty方法实现目标
    主动学习
    小知识
    大脑的处理模式
    真正的随笔
  • 原文地址:https://www.cnblogs.com/YY56/p/4707764.html
Copyright © 2020-2023  润新知