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;
}
原文地址:https://www.cnblogs.com/TnT2333333/p/6880773.html