1. 程式人生 > >【BZOJ1098】[POI2007]辦公樓biu

【BZOJ1098】[POI2007]辦公樓biu

edge dash pre void mes zoj () space ash

題目一開始看以為和強聯通分量有關,後來發現是無向邊,其實就是求原圖的補圖的聯通塊個數和大小。學習了黃學長的代碼,利用鏈表來優化,其實就是枚舉每一個人,然後把和他不相連的人都刪去放進同一個聯通塊裏,利用bfs來實現。——by VANE

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
const int M=4000005;
struct edge{int to,next;}e[M];
int a[N],q[N];
int pre[N],next[N],last[N];
int bel[N],cnt,ans,n,m;
bool vis[N],t[N]; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } void del(int x) { int tmp=pre[x]; next[tmp]=next[x]; pre[next[x]]=tmp; } void bfs(int x) { int head=0,tail=1; q[0]=x;
while(head!=tail) { a[ans]++; int now=q[head++]; for(int i=last[now];i;i=e[i].next) t[e[i].to]=1; for(int i=next[0];i<=n;i=next[i]) if(!t[i]) del(i),q[tail++]=i; for(int i=last[now];i;i=e[i].next)t[e[i].to]=0; } } int main() { scanf(
"%d%d",&n,&m); for(int i=0;i<=n;++i) next[i]=i+1; for(int i=1;i<=n+1;++i) pre[i]=i-1; for(int i=1;i<=m;++i) { int u,v;scanf("%d%d",&u,&v); insert(u,v); } for(int i=next[0];i<=n;i=next[0]) del(i),ans++,bfs(i); printf("%d\n",ans); sort(a+1,a+1+ans); for(int i=1;i<=ans;++i) printf("%d ",a[i]); }

【BZOJ1098】[POI2007]辦公樓biu