POJ2117 Electricity 題解 tarjan點雙連通分量 割點

題目鏈接:http://poj.org/problem?id=2117

題目大意:

給定一個由 \(n\)個點 \(m\) 條邊構成的無向圖,請你求出該圖刪除一個點之後,連通塊最多有多少。

解題思路:

tarjan,判斷 \(u\) 的子節點有幾個 \(v\) 滿足 \(low[v] \ge dfn[u]\) 就是答案,但是同時如果 \(u\) 不是這個 dfs 樹的根節點,個數還要加 \(1\)

示例程序1(C++11,POJ不支持):

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;

int n, m, dfn[maxn], low[maxn], ts, ans, root;
vector<int> g[maxn];

void init() {
    for (int i = 0; i < n; i++) g[i].clear(), dfn[i] = low[i] = 0;
    ts = ans = 0;
}

void tarjan(int u, int p) {
    dfn[u] = low[u] = ++ts;
    int cnt = 0;
    for (auto v : g[u]) {
        if (v != p) {
            if (!dfn[v]) {
                tarjan(v, u), low[u] = min(low[u], low[v]);
                if (dfn[u] <= low[v])
                    cnt++;
            }
            else
                low[u] = min(low[u], dfn[v]);
        }
    }
    if (u != root) cnt++;
    ans = max(ans, cnt);
}

int main() {
    while (~scanf("%d%d", &n, &m) && n) {
        init();
        for (int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        int cnt = 0;
        for (root = 0; root < n; root++)
            if (!dfn[root])
                cnt++, tarjan(root, -1);
        printf("%d\n", ans + cnt - 1);
    }
    return 0;
}

示例程序2(POJ支持):

#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
const int maxn = 10010;

int n, m, dfn[maxn], low[maxn], ts, ans, root;
vector<int> g[maxn];

void init() {
    for (int i = 0; i < n; i++) g[i].clear(), dfn[i] = low[i] = 0;
    ts = ans = 0;
}

void tarjan(int u, int p) {
    dfn[u] = low[u] = ++ts;
    int cnt = 0;
    int sz = g[u].size();
    for (int i = 0; i < sz; i++) {
        int v = g[u][i];
        if (v != p) {
            if (!dfn[v]) {
                tarjan(v, u), low[u] = min(low[u], low[v]);
                if (dfn[u] <= low[v])
                    cnt++;
            }
            else
                low[u] = min(low[u], dfn[v]);
        }
    }
    if (u != root) cnt++;
    ans = max(ans, cnt);
}

int main() {
    while (~scanf("%d%d", &n, &m) && n) {
        init();
        for (int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        int cnt = 0;
        for (root = 0; root < n; root++)
            if (!dfn[root])
                cnt++, tarjan(root, -1);
        printf("%d\n", ans + cnt - 1);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章