• poj 2117 Electricity(tarjan求割点删掉之后的连通块数)


    题目链接:http://poj.org/problem?id=2117

    题意:求删除一个点后,图中最多有多少个连通块。

    题解:就是找一下割点,根节点的割点删掉后增加son-1(son为子树个数),非根节点删掉之后++

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int N = 1e4 + 10;
    const int M = 1e6 + 10;
    struct TnT {
        int v , next;
        bool cut;
    }edge[M];
    int head[N] , e;
    int Low[N] , DFN[N] , Stack[N] , add_block[N];
    bool Instack[N];
    bool cut[N];
    int Index , bridge , top;
    void init() {
        memset(head , -1 , sizeof(head));
        e = 0;
    }
    void add(int u , int v) {
        edge[e].v = v , edge[e].next = head[u] ,edge[e].cut = false , head[u] = e++;
    }
    void Tarjan(int u , int pre) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        int son = 0;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            v = edge[i].v;
            if(v == pre) continue;
            if(!DFN[v]) {
                son++;
                Tarjan(v , u);
                Low[u] = min(Low[u] , Low[v]);
                if(Low[v] > DFN[u]) {
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                }
                if(u != pre && Low[v] >= DFN[u]) {
                    cut[u] = true;
                    add_block[u]++;
                }
            }
            else if(Instack[v]) Low[u] = min(Low[u] , DFN[v]);
        }
        if(u == pre && son > 1) cut[u] = true;
        if(u == pre) add_block[u] = son - 1;
        Instack[u] = false;
        top--;
    }
    int main() {
        int p , c;
        while(~scanf("%d%d" , &p , &c)) {
            if(p == 0 && c == 0) break;
            init();
            for(int i = 0 ; i < c ; i++) {
                int u , v;
                scanf("%d%d" , &u , &v);
                add(u , v);
                add(v , u);
            }
            memset(DFN , 0 , sizeof(DFN));
            memset(Instack , false , sizeof(Instack));
            memset(add_block , 0 , sizeof(add_block));
            memset(cut , false , sizeof(cut));
            int cnt = 0;
            Index = 0 , bridge = 0 , top = 0;
            for(int i = 0 ; i < p ; i++) {
                if(!DFN[i]) {
                    Tarjan(i , i) , cnt++;
                }
            }
            int MAX = 0;
            for(int i = 0 ; i < p ; i++) MAX = max(MAX , cnt + add_block[i]);
            printf("%d
    " , MAX);
        }
        return 0;
    }
    
  • 相关阅读:
    [python] 类组合与聚合关系
    [python] 伪私有属性,防止变量名冲突
    [vim] 配置文件之常用命令模式
    [VIM] 编辑器---多行注释和取消注释及多行复制和黏贴
    [Visual Studio Code] 执行python
    [C] 编译器codeblocks安装注意
    字符串全排列
    集合全量子集提取
    random函数详解
    Solr常用命令总结
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6881474.html
Copyright © 2020-2023  润新知