# UVA - 796 Critical Links (tarjan,无向图桥)

```#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;const int maxn = 1e3+10;
const int max_edge = 1e6+5;
struct Edge
{
int to, next;
bool cut;
}edge[max_edge];
int id, dfn[maxn], low[maxn];
int num;
{
edge[tot].to = v;
edge[tot].cut = false;
}
//tarjan的割边求法
void tarjan(int u, int f)
{
//时间戳更新
dfn[u] = low[u] = ++id;
for(int i = head[u]; i!=-1; i = edge[i].next)
{
int v = edge[i].to;
if(v == f) continue;
//深搜已经更新low值
if(!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
//tarjan算法割边确定的结论low[v]>dfn[u](桥>，割点>=)
if(low[v]>dfn[u])
{　　　　　　　　　//由于无向图边是连着存的,所以就用 ^ 得到所用有向边代替的另一个边 (0^1=1, 1^1=0)，网上看到大佬的写法　　　　　　　　　//当然我们也可以使用 奇数向下取偶，偶数向上取奇
edge[i].cut = edge[i^1].cut = true;
num++;
}
}
else low[u] = min(low[u], dfn[v]);
}
}
void init()
{
id = num = tot = 0;
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
}
int main()
{
int n;
while(~scanf("%d", &n))
{
init();
int u, m, v;
for(int i = 1; i<=n; i++)
{
scanf("%d (%d)", &u, &m);
for(int j = 1; j<=m; j++)
{
scanf("%d", &v);
}
}
for(int i = 0; i<n; i++)
if(!dfn[i])
tarjan(i, i);

vector<pair<int, int> >a;
for(int u = 0; u<n; u++)
for(int i = head[u]; i!=-1; i = edge[i].next)
{
//按升序排列
if(edge[i].cut && u < edge[i].to)
a.push_back(make_pair(u, edge[i].to));
}
sort(a.begin(), a.end());
for(int i = 0; i<a.size(); i++)
printf("%d - %d\n", a[i].first, a[i].second);
printf("\n");
}
}```

UVA - 796 Critical Links (tarjan,无向图桥)

(0)
(0)