首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

HDU 4587 TWO NODES:雙連通分量與割點應用,求移除兩點後最大連通塊

     編輯:關於C

題目大意

無向圖 N≤5000 點、M 條邊。移除任意 2 個點,求剩餘圖中最大連通分量點數的最大可能值。

核心思路:兩次割點分析

  1. 第一層:枚舉移除的第一個點 del。
  2. 在 del 移除後的圖中,跑 Tarjan 割點演算法,得到每個點的割點屬性 iscut[u](改為計數:移除 u 後增加的連通塊數)。
  3. 同時計算移除 del 後的基礎連通塊數 sum(DFS 森林樹根數)。
  4. 對於此 del,最佳第二個點即使 iscut[u] 最大者。總連通塊 = sum + max_cut。
  5. 枚舉所有 del 取最大值。

Tarjan 割點模板(計數版)


int pre[MAXN], low[MAXN], iscut[MAXN], dfs_clock;
int del; // 當前移除的點

int dfs(int u, int fa) {
    int lowu = pre[u] = ++dfs_clock;
    for (int i=head[u]; ~i; i=edge[i].next) {
        int v = edge[i].to;
        if (v == del) continue; // 跳過已移除點
        if (!pre[v]) {
            int lowv = dfs(v, u);
            lowu = min(lowu, lowv);
            if (lowv >= pre[u]) iscut[u]++; // u 是割點,子樹 v 會分離
        } else if (pre[v] < pre[u] && v != fa) {
            lowu = min(lowu, pre[v]);
        }
    }
    if (fa < 0) iscut[u]--; // 根節點修正
    return lowu;
}

完整流程


void solve() {
    int ans = 0;
    for (int del=0; del

複雜度分析

  • 外層枚舉 del:O(N)
  • 每次 Tarjan:O(N+M)
  • 總計 O(N(N+M)),N=5000 時約 2.5e7 操作,C++ 1s 內可過。

關鍵細節

  1. iscut[u]++ 而非布林,直接得到移除 u 後新增的連通塊數。
  2. 根節點 iscut[root]--,因為根無父節點,其子樹數即為割點增加數,但演算法會多算一次。
  3. 圖可能不連通,基礎連通塊 base_cc 需正確計數。
  4. 邊雙向儲存,鄰接表 head/edge/next 結構。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved