[BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】
生活随笔
收集整理的這篇文章主要介紹了
[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】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 类型提示的实现
- 下一篇: Xmpp实现简单聊天系列 --- ②用户