模板题:Tarjan算法求割点,桥
- UVA - 796 Critical Links Tarjan求割点个数
题目链接:
Vjudge
题意: 给定N个顶点若干条边, 求割点个数。
思路:模板题。套用kuangbin大牛的 Tarjan 模板。
#include <bits/stdc++.h>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define fst first
#define snd second
const int MAXN = 100 + 5;
const int MAXM = MAXN * MAXN * 2 + 5;
struct Edge {
int v, next;
Edge() {}
Edge(int v, int next) : v(v), next(next) {}
} edge[MAXM];
int head[MAXN], tot;
int low[MAXN], dfn[MAXN], add_block[MAXN];
int Index;
int N, res;
char buf[300];
void add_edge(int u, int v) {
edge[tot] = Edge(v, head[u]);
head[u] = tot++;
}
void Tarjan(int u, int pre) {
int v, son = 0;
low[u] = dfn[u] = ++Index;
for (int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if (v == pre) continue;
if (!dfn[v]) {
son ++;
Tarjan(v, u);
low[u] = min(low[u], low[v]);
if (u != pre && low[v] >= dfn[u]) {
add_block[u] ++;
}
} else {
low[u] = min(low[u], dfn[v]);
}
if (u == pre) {
add_block[u] = son - 1;
}
}
}
void init() {
tot = 0;
memset(head, -1, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(add_block, 0, sizeof(add_block));
Index = res = 0;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while (~scanf("%d\n", &N) && N) {
int u, v;
init();
while (gets(buf) != NULL) {
if (buf[0] == '0') break;
char* p = strtok(buf, " ");
sscanf(p, "%d", &u);
p = strtok(NULL, " ");
while (p) {
sscanf(p, "%d", &v);
p = strtok(NULL, " ");
add_edge(u, v);
add_edge(v, u);
}
}
for (int i = 1; i <= N; i++) {
if (!dfn[i]) Tarjan(i, i);
}
for (int i = 1; i <= N; i++) {
if (add_block[i]) res ++;
}
printf("%d\n", res);
}
return 0;
}
- UVA - 796 Critical Links Tarjan求桥
题目链接:
Vjudge
题意:给定若干顶点,和若干条边组成的无向图,求桥的个数,并且依次打印出每条桥的两个端点。顶点个数题目没有给出,测试在100个顶点以内吧。注意每组数据输出空行。结果保存在set中,去重。
#include <bits/stdc++.h>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define fst first
#define snd second
typedef pair<int, int> PII;
const int MAXN = 100 + 5;
const int MAXM = MAXN * MAXN * 2 + 5;
struct Edge {
int v, next;
bool cut;
Edge() {}
Edge(int v, int next, bool cut) : v(v), next(next), cut(cut) {}
} edge[MAXM];
int head[MAXN], tot;
int low[MAXN], dfn[MAXN];
int Index, top;
int bridge;
int N, M;
set<PII> res;
void add_edge(int u, int v) {
edge[tot] = Edge(v, head[u], false);
head[u] = tot++;
}
void Tarjan(int u, int pre) {
int v;
low[u] = dfn[u] = ++Index;
for (int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if (v == pre) continue;
if (!dfn[v]) {
Tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) {
bridge++;
edge[i].cut = true;
edge[i ^ 1].cut = true;
res.insert(make_pair(min(u, v), max(u, v)));
}
} else if (low[u] > dfn[v]) {
low[u] = dfn[v];
}
}
}
void init() {
tot = Index = 0;
bridge = 0;
memset(dfn, 0, sizeof(dfn));
memset(head, -1, sizeof(head));
res.clear();
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
int u, v;
while (~scanf("%d", &N)) {
init();
for (int i = 0; i < N; i++) {
scanf("%d (%d)", &u, &M);
while (M --) {
scanf("%d", &v);
add_edge(u, v);
add_edge(v, u);
}
}
for (int i = 0; i < N; i++) {
if (!dfn[i]) Tarjan(i, i);
}
printf("%d critical links\n", bridge);
for (set<PII>::iterator iter = res.begin(); iter != res.end(); iter++) {
printf("%d - %d\n", (*iter).fst, (*iter).snd);
}
puts("");
}
return 0;
}