• uva 796 C


    题目链接:https://vjudge.net/contest/67418#problem/C

    题意:求出桥的个数并且按顺序输出

    题解:所谓桥就是去掉这条边后连通块增加,套用一下模版就行。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 1e6 + 10;
    struct TnT {
        int v , next;
        bool cut;
    }edge[M];
    vector<pair<int , int> >ans;//用来存桥
    int head[N] , e;
    int Low[N] , DFN[N] , Stack[N];
    int Index , top;
    bool Instack[N];
    bool cut[N];
    int add_block[N];
    int bridge;
    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++;
                if(!DFN[v]) {
                    son++;
                    Tarjan(v , u);
                    Low[u] = min(Low[u] , Low[v]);
                }
                if(Low[v] > DFN[u]) {
                    //只有在存v使得low(v)>DFN(u)才能构成桥
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                    //这么处理的原因在于add两次一奇一偶
                }
                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 n;
        while(scanf("%d" , &n) == 1) {
            init();
            int u;
            int k;
            int v;
            for(int i = 1 ; i <= n ; i++)
            {
                scanf("%d (%d)" , &u , &k);
                while(k--) {
                    scanf("%d",&v);
                    if(v <= u) continue;//避免反复加边
                    add(u , v);
                    add(v , u);
                }
            }
            memset(DFN , 0 , sizeof(DFN));
            memset(Instack , false , sizeof(Instack));
            memset(cut , false , sizeof(cut));
            memset(add_block , 0 , sizeof(add_block));
            Index = 0 , top = 0 , bridge = 0;
            for(int i = 0 ; i < n ; i++)
                if(!DFN[i]) Tarjan(i , i);
            printf("%d critical links
    " , bridge);
            ans.clear();
            for(int i = 0 ; i < n ; i++) {
                for(int j = head[i] ; j != -1 ; j = edge[j].next) {
                    int v = edge[j].v;
                    if(edge[j].cut && i < v) ans.push_back(make_pair(i , v));
                }
            }
            sort(ans.begin() , ans.end());
            for(int i = 0 ; i < ans.size() ; i++) {
                printf("%d - %d
    " , ans[i].first , ans[i].second);
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    My family No.1
    机器学习之数学原理笔记(五)
    机器学习之数学原理笔记(四)
    机器学习之数学原理笔记(三)
    机器学习笔记(一)
    有关矩阵的几点总结
    C++笔记(二)------ 头文件
    网络编程基础
    第四次测试--面向对象
    面试题整理
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6880773.html
Copyright © 2020-2023  润新知