日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】

發布時間:2025/7/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:BZOJ - 1098

?

題目分析

只有兩個點之間有邊的時候它們才能在不同的樓內,那么就是說如果兩個點之間沒有邊它們就一定在同一座樓內。

那么要求的就是求原圖的補圖的連通塊。

然而原圖的補圖的邊數是 n^2 級別的,非常龐大,我們不能直接把補圖求出來。

可以使用一種用鏈表優化BFS的做法,開始時將所有的點加到一個鏈表里。

每次找一個連通塊的時候BFS,在鏈表中取出一個點,在鏈表中刪除,加入隊列,然后每次取出隊首元素x,枚舉x的每一條邊,將邊的終點y從鏈表中刪去,加到一個臨時的鏈表中存儲。

這樣枚舉完 x 的所有邊之后,原鏈表里剩余的點就是與 x 沒有邊的,這些點在補圖里與 x 就是有邊的,將這些點加入隊列。

然后用臨時的鏈表替代原鏈表,原鏈表中就是剩下的點了。

這樣BFS幾次就可以求出所有連通塊了。

每一個點都只被從鏈表中刪去1次,每條邊都只遍歷了一次,總的時間復雜度是 O(n + m)。

?

代碼

#include <iostream> #include <cstdlib> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> #include <queue>using namespace std;const int MaxN = 100000 + 5, MaxM = 2000000 + 5;inline void Read(int &Num) {char c; c = getchar();while (c < '0' || c > '9') c = getchar();Num = c - '0'; c = getchar();while (c >= '0' && c <= '9') {Num = Num * 10 + c - '0';c = getchar();} }int n, m, Top, R1, R2, Sum; int Ans[MaxN], Last[MaxN], Next[MaxN];bool InList[MaxN];struct Edge {int v;Edge *Next; } E[MaxM * 2], *P = E, *Point[MaxN];inline void AddEdge(int x, int y) {++P; P -> v = y;P -> Next = Point[x]; Point[x] = P; }queue<int> Q;inline void Add(int x, int y) {Next[y] = Next[x];if (Next[x]) Last[Next[x]] = y;Next[x] = y;Last[y] = x; }inline void Delete(int x) {if (Last[x]) Next[Last[x]] = Next[x];if (Next[x]) Last[Next[x]] = Last[x]; }void BFS() {while (!Q.empty()) Q.pop();Q.push(Next[R1]);InList[Next[R1]] = false;Delete(Next[R1]);int x, y;++Top;while (!Q.empty()) {x = Q.front();++Sum;++Ans[Top];Q.pop(); R2 = n + 2;Last[R2] = Next[R2] = 0;for (Edge *j = Point[x]; j; j = j -> Next){y = j -> v;if (!InList[y]) continue;Delete(y);Add(R2, y);}for (int i = Next[R1]; i; i = Next[i]) {Q.push(i);InList[i] = false;}Next[R1] = Next[R2];Last[Next[R1]] = R1;} }int main() {scanf("%d%d", &n, &m);int a, b;for (int i = 1; i <= m; ++i) {Read(a); Read(b);AddEdge(a, b);AddEdge(b, a);}Top = 0; Sum = 0;R1 = n + 1;for (int i = 1; i <= n; ++i) Add(R1, i);for (int i = 1; i <= n; ++i) InList[i] = true;while (Sum < n) BFS();printf("%d\n", Top);sort(Ans + 1, Ans + Top + 1);for (int i = 1; i <= Top; ++i) printf("%d ", Ans[i]);return 0; }

  

轉載于:https://www.cnblogs.com/JoeFan/p/4322722.html

總結

以上是生活随笔為你收集整理的[BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。