题目描述
- 对于一个图, 如果它的点集能被分成两个部分, 使得在原图中每一部分之间的点没有任何边相连,则该图被称为二分图。
- 现在给定一个无向图,每次增加一条边,或者删除一条边。要求您每次判断它是不是二分图。
数据范围
暴力
- 对于前30分,我们显然可以直接暴力。
- 如果是插入操作就直接把边加进去,然后判断一下它是否会组成奇环,如果是的话就直接输出“NO”,然后看其中的换最早删去的边,很显然至少要等到那条边被删去时才有可能重新输出“YES”。
- 这样30分就到手了。
只有插入操作
- 我们可以用并查集来维护一下。
- 因为只有加边,很显然只要输出“NO”,以后就一定只会输出“NO”了。
- 所以我们就可以直接建立一个并查集来判断是否有奇环的出现。
- 紧接着再加上暴力,你可以拿到50分的好成绩。
正解
- 删除操作是并查集的“天敌”,很自然地我们会想到避免进行删除操作。
- 注意到每条边存在的时间都一定是一个连续的区间,所以我们可以建一个以时间为下标的权值线段树。然后把每条边按其相应的出现时间扔进线段树里面。这样我们查询一个时间点的时候就可以从根到叶子只加边,不删边。
- 但如果每个时间点一一分开查询的话,很显然我们是可以构造出数据使这种方法超时,所以我们不妨以一种遍历(dfs)的方式来遍历这棵权值线段树。递归进去显然就是简单的加边。
- 但问题来了,回溯的时候不就又要删边了吗?怎么搞?
- 但只要我们细心观察,就会发现这里的删边和原来的删边有一些不一样:这里删的边和在这一层插入的边是一样的。也就是说在进行完删除操作之后,整个并查集其实就像是没有被动过一样,所以我们可以暴力把在这一层插入边时所修改的并查集上的东西记录下来,到时候回溯时再暴力改回去。做好按秩合并,不要路径压缩,这样插入边时并查集改动得比较少,容易改回来。
- 然后你就发现你会做这道题了。
注意事项
- 把边扔进线段树里时最好用前向星来存储。