BZOJ 1098 [POI2007]办公楼biu 链表

description

Bytel is a mobile telephony potentate. Each employee has been issued a company phone, the memory ofwhich holds the numbers of some of his co-workers (all of them have his number in their phones as well).

Due to dynamic growth of their operations the board of directors intends to move company headquaters tonew office buildings. It has been decided - in order to boost work efficiency - that every pair of employeesworking in different buildings should know (reciprocally) each others phone number i.e. the memory of theircompany phone ought to hold necessary phone numbers.

Simultaneously, the board have decided to rent as many office buildings as possible to ensure good workingconditions. Help the board of Bytel to plan the number of office buildings and their size in accordancewith the aforementioned requirements.

TaskWrite a programme which:

reads the description of employees' phone number lists from the standard input calculates the maximal number of office buildings and their sizes, satisfying board's conditions writes the outcome to the standard output.

input

The first line of the standard input consists of two integers:  and (),separated by single spaces, denoting the number of Bytel employees and the number of pairs of employeeswho have their numbers in company phones, respectively. The employees are numbered from  to .

Each of the following  lines contains a single pair of integers  and ( for ), separated by a single space, denoting that employees!

output

The first line of the standard output should contain a single integer: the maximal number of office buildingsthat Bytel should rent. The second should contain a non-decreasing sequence of positive integers, separatedby singe spaces, denoting the sizes of the office buildings (i.e. the numbers of employees working there).

Should there exist more than one correct answer - write out any one of them.

给出一个图(N个点,M条边),让你把此图分成尽可能多的集合,满足任意不在同一集合的点之间都有边相连。

简化为:求反图的联通块个数

那么可以这样考虑,将每个点转换成链表

将联通块求出来,同时不断用与当前节点在原图有连边的节点加入新链表,统计剩余列表并加入至队列

再用新链表代替老链表,反复进行即可

#include<cstdio>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cctype>
using namespace std;
const int N=1000010,M=2000010;
int read(){
    char c;int x=0,f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^48);
    return x*f;
}
vector<int> G[N];
queue<int> Q;
int ans[N],pr[N],ne[N];
bool in[N];
int tot,sum;
int n,m;
void add(int x,int y){
    ne[y]=ne[x];
    if(ne[x])pr[ne[x]]=y;
    ne[x]=y;pr[y]=x;
}
void del(int x){
    if(pr[x])ne[pr[x]]=ne[x];
    if(ne[x])pr[ne[x]]=pr[x];
}
void BFS(){
    while(!Q.empty())Q.pop();
    Q.push(ne[n+1]);
    in[ne[n+1]]=false;del(ne[n+1]);
    ++tot;
    while(!Q.empty()){
        int u=Q.front();
        ++sum;++ans[tot];
        Q.pop();
        pr[n+2]=ne[n+2]=0;
        for(int i=0,i_end=G[u].size();i<i_end;++i){
            int v=G[u][i];
            if(!in[v])continue;
            del(v);//delete it
            add(n+2,v);//add in new list
        }
        for(int i=ne[n+1];i;i=ne[i]){
            Q.push(i);
            in[i]=false;
        }
        ne[n+1]=ne[n+2];
        pr[ne[n+1]]=n+1;
        //ls list takeplace last list
    }
    
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    tot=0,sum=0;
    for(int i=1;i<=n;++i)add(n+1,i);
    for(int i=1;i<=n;++i)in[i]=true;
    while(sum<n)BFS();
    printf("%d\n",tot);
    sort(ans+1,ans+1+tot);
    for(int i=1;i<=tot;++i)
        printf("%d ",ans[i]);
    return 0;
}

这让我想起了APIO2007的数据备份,可以多多写一写链表的优化

转载于:https://www.cnblogs.com/ndqzhang1111/p/6870219.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值