UVA796 - Critical Links - 桥

题目链接

分类Graph

1.题意概述
  • 给你一个图,要你按顺序求出图中所有的桥。
2.解题思路
  • 根据Tarjan求割边的算法找出所有low[v]>dfn[u]边就行,算是一道入门题。
3.AC代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define maxn 10010
/* head */
struct Edge {
    int to, next;
    bool cut;
} E[maxn << 1];
int head[maxn], cnt;
int dfn[maxn], low[maxn], sec;
int bridge, n;
void init() {
    memset(head, -1, sizeof head);
    memset(dfn, 0, sizeof dfn);
    memset(low, 0, sizeof low);
    cnt = sec = bridge = 0;
}
void addedge(int u, int v) {
    E[cnt].to = v;
    E[cnt].next = head[u];
    E[cnt].cut = 0;
    head[u] = cnt++;
}
void tarjan(int u, int fa) {
    dfn[u] = low[u] = ++sec;
    for (int i = head[u]; ~i; i = E[i].next) {
        int v = E[i].to;
        if (v != fa) {
            if (!dfn[v]) {
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
                if (low[v] > dfn[u]) {
                    ++bridge;
                    E[i].cut = 1;
                    E[i ^ 1].cut = 1;
                }
            }
            else low[u] = min(low[u], dfn[v]);
        }
    }
}
int main() {
    while (~scanf("%d", &n)) {
        init();
        rep(i, 0, n) {
            int u, m;
            scanf("%d (%d)", &u, &m);
            ++u;
            while (m--) {
                int v;
                scanf("%d", &v);
                ++v;
                addedge(u, v);
                addedge(v, u);
            }
        }
        rep(i, 1, n + 1) {
            if (!dfn[i]) tarjan(i, i);
        }
        printf("%d critical links\n", bridge);
        vector<PII> ans;
        rep(u, 1, n + 1) {
            for (int i = head[u]; ~i; i = E[i].next) {
                int v = E[i].to;
                if (E[i].cut && v > u) ans.pb(mp(u, v));
            }
        }
        sort(All(ans));
        int sz = SZ(ans);
        rep(i, 0, sz) printf("%d - %d\n", ans[i].fi - 1, ans[i].se - 1);
        puts("");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值