[BZOJ1098][POI2007]办公楼biu

题目描述

\(FGD\)开办了一家电话公司。

他雇用了\(N\)个职员,给了每个职员一部手机。

每个职员的手机里都存储有一些同事的电话号码。

由于\(FGD\)的公司规模不断扩大,旧的办公楼已经显得十分狭窄,\(FGD\)决定将公司迁至一些新的办公楼。

\(FGD\)希望职员被安置在尽量多的办公楼当中,这样对于每个职员来说都会有一个相对更好的工作环境。

但是,为了联系方便起见,如果两个职员被安置在两个不同的办公楼之内,他们必须拥有彼此的电话号码。

Input

第一行包含两个整数\(N(2<=N<=100000)\)\(M(1<=M<=2000000)\)

职员被依次编号为\(1,2,……,N\).以下\(M\)行,每行包含两个正数\(A\)\(B(1<=A<b<=n)\),表示职员\(a\)\(b\)拥有彼此的电话号码),\(li <= 1000\)

Output

包含两行。第一行包含一个数\(S\),表示\(FGD\)最多可以将职员安置进的办公楼数。

第二行包含\(S\)个从小到大排列的数,每个数后面接一个空格,表示每个办公楼里安排的职员数。

Sample Input

7 16
1 3 
1 4
1 5
2 3
3 4
4 5
4 7
4 6
5 6
6 7
2 4
2 7
2 5
3 5
3 7
1 7

Sample Output

3
1 2 4

链表优化广搜。。。

由题意得,即找到补图的每个连通块个数。

观察数据范围,点数很少,但是边数却很多。

直接暴力广搜肯定会炸裂。

那我们有两种选择,并查集或优化广搜。

并查集肯定很麻烦,那我们选择了优化广搜。

我们发现广搜的复杂度都堆积到了枚举点上面。

于是,我们要想办法去优化这一过程。

怎么优化呢?

我们需要一个数据结构,支持遍历所有的点,并支持删除操作。

是什么呢?

链表!!!

我们一开始将所有点都放进链表里。

每遍历了一个点就将该点从链表中删除。

由此优化广搜。

代码如下

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
#define reg register
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,e) for(reg int i=H[e];i;i=G[i].nxt)
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define int long long
 
inline int Read() {
    int res=0,f=1;
    char c;
    while(c=getchar(),c<48||c>57)if(c=='-')f=0;
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>=48&&c<=57);
    return f?res:-res;
}
 
template<class T>inline bool Min(T &a,T const&b) {
    return a>b?a=b,1:0;
}
template<class T>inline bool Max(T &a,T const&b) {
    return a<b?a=b,1:0;
}
const int N=1e5+5,M=2e6+5;
 
int n,m,Ans,tot,H[N],Sz[N],mark[N],vis[N],L[N],R[N];
 
struct edge {
    int nxt,to;
} G[M<<1];
 
void Add(int a,int b) {
    G[++tot]=(edge)<%H[a],b%>,H[a]=tot;
}
 
void Del(int x) {
    vis[x]=1,L[R[x]]=L[x],R[L[x]]=R[x];
}
 
void BFS(int x) {
    queue<int>Q;
    Q.push(x);
    while(!Q.empty()) {
        Sz[Ans]++;
        int x=Q.front();
        Q.pop();
        int o=0;
        for(reg int i=H[x]; i; i=G[i].nxt)mark[G[i].to]=1,o++;
        for(reg int i=R[0]; i; i=R[i]) {
            if(vis[i]||mark[i])continue;
            Q.push(i),Del(i);
        }
        for(reg int i=H[x]; i; i=G[i].nxt)mark[G[i].to]=0;
    }
}
 
signed main() {
    n=Read(),m=Read();
    rep(i,1,m) {
        int a=Read(),b=Read();
        Add(a,b),Add(b,a);
    }
    rep(i,0,n)L[i]=i-1,R[i]=i+1;
    R[n]=0;
    rep(i,1,n)if(!vis[i])Ans++,Del(i),BFS(i);
    printf("%d\n",Ans);
    sort(Sz+1,Sz+Ans+1);
    rep(i,1,Ans)printf("%d ",Sz[i]);
}
posted @ 2019-08-05 14:07  dsjkafdsaf  阅读(155)  评论(0编辑  收藏  举报