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

POJ 2236 & 1611:並查集經典應用兩則

     編輯:關於C++

POJ 2236 Wireless Network:動態加點連通性查詢

題意

N (≤ 1000) 台電腦,坐標已知,通訊距離 ≤ d。初始均故障。操作:
`O x`:修復電腦 x。
`S x y`:查詢 x、y 是否連通(通過已修復電腦中繼)。

解法

  • 預計算所有電腦對距離平方,判斷是否 ≤ d²。
  • 並查集維護已修復電腦的連通分量。
  • `O x`:標記 x 已修復,遍歷所有**已修復**電腦 y,若 `dist(x,y) ≤ d²` 則 `union(x,y)`。
  • `S x y`:直接 `find(x)==find(y)` 判斷。

關鍵代碼


struct Point { int x, y; } p[1005];
bool repaired[1005];
int pre[1005], rnk[1005];

void unite(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) return;
    if (rnk[x] < rnk[y]) swap(x, y);
    pre[y] = x;
    if (rnk[x] == rnk[y]) rnk[x]++;
}

POJ 1611 The Suspects:傳染病擴散分組統計

題意

N (≤ 30000) 學生,M 組。0 號感染。同組傳染,組之間可交叉。求最終感染總人數。

解法

  • 每組內所有學生 `union` 到第一個學生。
  • 最後統計 `find(i) == find(0)` 的人數。

關鍵代碼


struct UF {
    int par[MAXN], rnk[MAXN];
    void init(int n) { for(int i=0;i<=n;++i){par[i]=i;rnk[i]=1;} }
    int find(int x) { return par[x]==x?x:par[x]=find(par[x]); }
    void unite(int x, int y) {
        x=find(x); y=find(y); if(x==y) return;
        if(rnk[x]

共同核心:並查集模板

  • 路徑壓縮 `find` + 按秩/按大小合併 `unite`。
  • 靜態連通性(1611)或動態加點(2236)均完美適用。
  • 時間近似 O(α(N)),極快。

總結

POJ 2236 與 1611 分別展示了並查集在「動態激活節點連通性」與「群組傳遞閉包」中的應用。掌握標準並查集模板,此類問題皆可秒殺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved