题目连接
题意:
1)给你一个图,然后让你求图中桥的个数
2)要求按字典序输出
3)并且要求第一个点的值小于第二个点的值
思路:
1)Tarjan求桥
2)要求按字典序输出,所以可以用set + pair 来储存
3)在插入set时比较一下大小再插入。
AC :
#include<iostream>
#include<math.h>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#define LL long long
#define P pair<int, int>
using namespace std;
const int MAXN = 1e5 + 10;
int head[MAXN], cnt, dfn[MAXN], low[MAXN], tot;
set<P> ans;
struct Edge{
int to, dis, next;
}edge[MAXN << 1];
void add_edge(int u, int v, int dis) {
edge[++cnt].to = v;
edge[cnt].dis = dis;
edge[cnt].next = head[u];
head[u] = cnt;
}
void Tarjan (int x, int fa) {
low[x] = dfn[x] = ++tot;
for(int i = head[x]; i; i = edge[i].next) {
int to = edge[i].to;
if(to == fa) continue; //因为是无向图所以把回边给跳过了
if(!dfn[to]) { //没搜过
Tarjan(to, x);
low[x] = min(low[x], low[to]);
if(dfn[x] < low[to]) { //这条连线是关键线
ans.insert(make_pair(min(x, to), max(x, to)));
}
} else { //搜过了,改当前的最短时间戳的值
low[x] = min(low[x], dfn[to]);
}
}
}
void init() {
cnt = 1;
tot = 0;
memset(head, 0, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
ans.clear();
}
int main() {
int n, m;
while(scanf("%d", &n) != EOF) {
init();
int x, y, m;
for (int i = 1; i <= n; ++i) {
scanf("%d (%d)", &x, &m);
for (int i = 1; i <= m; ++i) {
scanf("%d", &y);
add_edge(x, y, 0);
add_edge(y, x, 0);
}
}
for (int i = 0; i < n; ++i) {
if(!dfn[i])
Tarjan(i, i);
}
int sum = ans.size();
printf("%d critical links\n", sum);
for(auto it : ans) {
printf("%d - %d\n", it.first, it.second);
}
printf("\n");
}
return 0;
}