题目链接: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; }