BZOJ_1098_[POI2007]办公楼biu_链表优化BFS
Posted fcwww
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ_1098_[POI2007]办公楼biu_链表优化BFS相关的知识,希望对你有一定的参考价值。
BZOJ_1098_[POI2007]办公楼biu_链表优化BFS
Description
FGD开办了一家电话公司。他雇用了N个职员,给了每个职员一部手机。每个职员的手机里都存储有一些同事的
电话号码。由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决定将公司迁至一些新的办公楼。FG
D希望职员被安置在尽量多的办公楼当中,这样对于每个职员来说都会有一个相对更好的工作环境。但是,为了联
系方便起见,如果两个职员被安置在两个不同的办公楼之内,他们必须拥有彼此的电话号码。
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
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
1 2 4
其实就是求补图的联通快个数,然而边数是$n^2$级别的不能遍历每条没有出现的边。
考虑用链表优化bfs。
每次用当前点x把与之相连的所有点在链表中标记。
然后删除那些与x没有边相连的点并扩展。
一共n个点总共遍历m条边因此时间复杂度是$O(n+m)$的。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define RR register inline char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd() { RR int x=0; RR char s=nc(); while(s<‘0‘||s>‘9‘) s=nc(); while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc(); return x; } #define N 100050 #define M 2000050 int L[N],R[N],n,m,head[N],to[M<<1],nxt[M<<1],Q[N],l,r,pos[N][2],cnt,ans[N],num[N][2],tot; int vis[N]; inline void add(int u,int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void del(int x) { L[R[x]]=L[x]; R[L[x]]=R[x]; } int main() { n=rd(); m=rd(); int i,x,y; for(i=1;i<=m;i++) { x=rd(); y=rd(); add(x,y); add(y,x); } for(i=1;i<=n;i++) L[i]=i-1,R[i]=i+1; R[0]=1; L[n+1]=n; while(R[0]!=n+1) { l=r=0; // puts("FUCK"); Q[r++]=R[0]; del(R[0]); int x; ans[0]++; while(l<r) { // puts("FUCK"); x=Q[l++]; ans[ans[0]]++; tot++; for(i=head[x];i;i=nxt[i]) vis[to[i]]=tot; for(i=R[0];i!=n+1;i=R[i]) { if(vis[i]!=tot) Q[r++]=i,del(i); } } } /*for(i=1;i<=n;i++) { if(!vis[i]) { ans[0]++; l=r=0; Q[r++]=i; while(l<r) { x=Q[l++];int j; ans[ans[0]]++; vis[x]=1; for(j=head[x];j;j=nxt[j]) { int y=to[j]; if(vis[y]) continue; vis[y]=1; L[R[pos[y][k]][k]][k]=L[pos[y][k]][k]; R[L[pos[y][k]][k]][k]=R[pos[y][k]][k]; if(!pos[y][!k]) { L[cnt[!k]][!k]=cnt[!k]+1; R[cnt[!k]+1][!k]=cnt[!k]; pos[y][!k]=++cnt[!k]; num[cnt[!k]][!k]=y; } } for(j=R[pos[x][k]][k];j;j=R[j][k]) { Q[r++]=num[j][k]; } for(j=head[x];j;j=nxt[j]) { pos[to[j]][k]=0; } } } }*/ sort(ans+1,ans+ans[0]+1); printf("%d\n",ans[0]); int flg=0; for(i=1;i<=ans[0];i++) { if(!flg) flg=printf("%d",ans[i]); else printf(" %d",ans[i]); } }
以上是关于BZOJ_1098_[POI2007]办公楼biu_链表优化BFS的主要内容,如果未能解决你的问题,请参考以下文章