补图(bzoj1098)

题解:

在原图中相连的两个点在补图中必然不相连 在补图中相连的点在原图中必然不会相连 所以我们考虑对于每个点做BFS 去查询其补图中联通块的大小 具体来说就是对于每个点去扩展其原图中没有连边的点并且这个点也没有被选入到补图 那么这个点与当前这个点必然在一个联通块里面 然后就能维护出补图联通块的个数以及每个联通块的大小 考虑用链表优化过程

(大概就是这个思路..我只是上来存个补图的板子)

复杂度 $O(n+m)$

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const int NM=2e6+10;
const double eps=1e-8;
const int mod=1e9+9;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[NM<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m;
typedef struct node{
int t,pre,last;
}node;
node d[MAXN];
bool tag[MAXN],flag[MAXN];
queue<int>que;
int num;
vector<int>ans;
void bfs(){
while(!que.empty()){
int x=que.front();que.pop();
link(x)tag[j->t]=1;
for(int k=d[0].last;k!=-1;k=d[k].last){
int y=k;
if(!tag[y]&&!flag[y]){
que.push(y);num++;flag[y]=1;
int pre=d[y].pre;
int last=d[y].last;
d[pre].last=last;
if(last!=-1)d[last].pre=pre;
d[y].last=d[y].pre=-1;k=pre;
}
}
link(x)tag[j->t]=0;
}
}
int main(){
n=read();m=read();
d[0].pre=-1;
inc(i,1,n){
d[i].t=i;
d[i].pre=i-1;
d[i-1].last=i;
}
d[n].last=-1;
int x,y;
inc(i,1,m){
x=read();y=read();
add(x,y);add(y,x);
}
inc(i,1,n){
if(flag[i])continue;
num=1;que.push(i);flag[i]=1;
int pre=d[i].pre;
int last=d[i].last;
d[pre].last=last;
if(last!=-1)d[last].pre=pre;
d[i].last=d[i].pre=-1;
bfs();
ans.pb(num);
}
sort(ans.begin(),ans.end());
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)printf("%d ",ans[i]);
printf("\n");
return 0;
}