[BZOJ1098][POI2007]办公楼biu

一个看上去非常玄学的代码

const int N=1e5+10,M=2e6+10;

int n,m;
int fa[N];
int Find(int x){ return fa[x]==x?x:fa[x]=Find(fa[x]); } vector <int> G[N];
typedef vector <int> ::iterator iter; void merge(int x,int y){
x=Find(x),y=Find(y);
if(x==y) return;
vector <int> tmp;tmp.clear();
if(G[x].size()>G[y].size()) swap(x,y);
int p=0;
for(reg int i=0;i<(int)G[x].size();i++){
while(p<(int)G[y].size()&&G[y][p]<G[x][i]) p++;
if(p>=(int)G[y].size()||G[y][p]!=G[x][i]) {
tmp.push_back(G[x][i]);
G[x].erase(G[x].begin()+i);
i--;
}
}
fa[y]=x;
rep(i,0,tmp.size()-1) merge(x,tmp[i]);
} int cnt[N];
int ans[N],ac;
bool go[N]; void Sort(vector <int> &V){
if(V.size()<20000) return sort(V.begin(),V.end());
memset(go,0,sizeof go);
rep(i,0,V.size()) go[V[i]]=true;
V.clear();
rep(i,1,n) if(go[i]) V.push_back(i);
} int num[N]; bool cmp(int x,int y){
return G[x].size()<G[y].size();
} int main(){
n=rd(),m=rd();
rep(i,1,n) fa[i]=num[i]=i;
rep(i,1,m) {
int u=rd(),v=rd();
G[u].push_back(v);
G[v].push_back(u);
}
rep(i,1,n) Sort(G[i]);
sort(num+1,num+n+1,cmp);
rep(i,1,n) if(Find(num[i])==num[i]) {
memset(go,0,sizeof go);
rep(j,0,G[num[i]].size()-1) go[G[num[i]][j]]=1;
rep(j,1,n) if(num[i]!=j&&!go[j]) merge(num[i],j);
}
rep(i,1,n) cnt[Find(i)]++;
rep(i,1,n) if(cnt[i]) ans[++ac]=cnt[i];
sort(ans+1,ans+ac+1);
printf("%d\n",ac);
rep(i,1,ac) printf("%d",ans[i]),putchar(i==ac?'\n':' ');
}

我这个代码大概是在讲这样的:

按照出度排序,没有连边的点必须合并,最后找集合个数

但是合并的时候要注意用y的答案更新x,这样y就不用再跑一次了(这里的总复杂度较为诡异)

更新过程:遍历x的边,如果y的边中没有x的这条边,那么就将其删去,并且将这个点合并


首先根据鸽巢原理,出度最小的点最大出度必然是\(\frac{m}{n}\)

它的边数也是\(\frac{m}{n}\)

每次和其他的点合并,这个复杂度是 \(\frac{m}{n} \cdot m\) (事实上是远远跑不到的!因为每次都会删去大量的边!)

复杂度似乎是有保证的

然后由于合并完之后也就剩下不到\(\frac{m}{n}\)个点了,所以这里就算你暴力\(O(n)\)合并也没关系

最后是你们担心的\(\frac{m}{n} \cdot m\)会TLE

瞪眼一看当\(m=2e6,n\)较小时就T了

哪你n较小时直接跑\(O(n^2)\)不就是了 吐舌头

注意时限是20s的这个代码还根本跑不满,所以自然不用担心!

tips: vector可以用链表优化更棒

5098: [BZOJ1098][POI2007]办公楼biu的更多相关文章

  1. BZOJ1098: [POI2007]办公楼biu

    从问题可以看出是求补图的连通块及点数 但补图太大.所以考虑缩小规模. 当一个点归属于一个连通块后,它以后就不需要了.所以可以用链表,删去这个点,也就减小了规模. 一个点开始bfs,每个点只会进队一次, ...

  2. 【链表】Bzoj1098[POI2007]办公楼biu

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...

  3. BZOJ1098 POI2007 办公楼biu 【链表+bfs】

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...

  4. bzoj 1098 [POI2007]办公楼biu bfs+补图+双向链表

    [POI2007]办公楼biu Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1543  Solved: 743[Submit][Status][Di ...

  5. 【BZOJ1098】[POI2007]办公楼biu

    题目一开始看以为和强联通分量有关,后来发现是无向边,其实就是求原图的补图的联通块个数和大小.学习了黄学长的代码,利用链表来优化,其实就是枚举每一个人,然后把和他不相连的人都删去放进同一个联通块里,利用 ...

  6. 【BZOJ】1098: [POI2007]办公楼biu(补图+bfs+链表)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1098 显然答案是补图连通块..... 想到用并查集...可是连补图的边都已经...n^2了...怎么 ...

  7. 【刷题】BZOJ 1098 [POI2007]办公楼biu

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD ...

  8. bzoj 1098 [POI2007] 办公楼 biu

    # 解题思路 画画图可以发现,只要是两个点之间没有相互连边,那么就必须将这两个人安排到同一个办公楼内,如图所示: 那,我们可以建立补图,就是先建一张完全图,然后把题目中给出的边都删掉,这就是一张补图, ...

  9. [POI2007]办公楼biu

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...

随机推荐

  1. 电脑远程连接windows阿里云服务器解决卡顿【小白教程】

    我们在阿里云服务器网页上进行远程连接进行操作,会卡顿.解决办法如下: 1.登录阿里云服务器,进入服务器控制台,复制服务器IP:  2.回到桌面,打开cmd命令窗口,输入mstsc  3.在‘’计算机’ ...

  2. Python 的 12 个学习方式

    Python 是世界上最受欢迎的编程语言之一,它受到了全世界各地的开发者和创客的欢迎.大多数 Linux 和 MacOS 计算机都预装了某个版本的 Python,现在甚至一些 Windows 计算机供 ...

  3. vue与webpack开发环境搭建:从无到有

    一个vue从无到有的搭建过程. 一.不论是webpack还是vue,最初的第一步就是安装node.js.它是基石. 从官网下载你需要的安装包:官网下载链接:http://nodejs.cn/downl ...

  4. jQuery(function(){})和$(function(){ }) 和 $(document).ready(function(){ })关系

    转自:https://www.jianshu.com/p/3b0fe5d07996 $(function(){ })和jQuery(function(){ })都是 $(document).ready ...

  5. mysql显示一张表的索引

    show index from tm_show.fulfillment_order;show index from tm_show.express_verify;show index from tra ...

  6. Codeforces A. Kyoya and Colored Balls(分步组合)

    题目描述: Kyoya and Colored Balls time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  7. hexo的jacman主题设置语言为英文后偶尔出现中文

    发现这个问题也好久了.问题的具体表现是在根目录下的_config.yml设置了语言为英文,但是每次发布后都会更换一次语言.今天看了文件结构,知道了,每换一次语言“英文.简体中文.繁体中文”,就是这三种 ...

  8. WPF系列 —— 控件添加依赖属性

    依赖属性的概念,用途 ,如何新建与使用.本文用做一个自定义TimePicker控件来演示WPF的依赖属性的简单应用. 先上TimePicker的一个效果图. 概念 和 用途:依赖属性是对传统.net ...

  9. 关于__int 128 的读入与输出

    inline __int128 read() { ,w=; ; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} )+(X<<)+(ch^),c ...

  10. Win10系统如何关闭自动更新?

    现在很多电脑的系统都升级到了win10了,win10已经渐渐普及到每个人的电脑中,但是,win10系统有一个功能特别讨人厌,我自认为挺讨厌这个功能的,它就是“自动更新”功能,你可能会说,自动更新不是挺 ...