题目链接: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\n" , 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\n" , ans[i].first , ans[i].second);
}
printf("\n");
}
return 0;
}