[POI 2007] 办公楼
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1098
[算法]
显然 , 答案为补图的连通分量个数
用链表优化BFS , 时间复杂度 : O(N + M)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define MAXM 2000010 struct edge { int to , nxt; } e[MAXM << 1]; int n , m , tot , cnt; int head[MAXN] , ans[MAXN] , L[MAXN] , R[MAXN]; bool visited[MAXN] , mark[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u , int v) { ++tot; e[tot] = (edge){v , head[u]}; head[u] = tot; } inline void del(int x) { R[L[x]] = R[x]; L[R[x]] = L[x]; } inline void bfs(int s) { queue< int > q; visited[s] = true; q.push(s); while (!q.empty()) { int cur = q.front(); q.pop(); ++ans[cnt]; for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to; mark[v] = true; } for (int i = R[0]; i; i = R[i]) { if (!mark[i] && !visited[i]) { visited[i] = true; del(i); q.push(i); } } for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to; mark[v] = false; } } } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { int u , v; read(u); read(v); addedge(u , v); addedge(v , u); } for (int i = 0; i <= n; i++) L[i] = i - 1 , R[i] = i + 1; R[n] = 0; for (int i = 1; i <= n; i++) { if (!visited[i]) { ++cnt; bfs(i); } } printf("%d\n" , cnt); sort(ans + 1 , ans + cnt + 1); for (int i = 1; i <= cnt; i++) printf("%d " , ans[i]); printf("\n"); return 0; }