Educational Codeforces Round 128
题目
https://codeforces.com/contest/1680/problem/F
给一个连通无向图,n点,m 边
点覆盖: (所有边至少一个点属于点集
lenient点覆盖: 是点覆盖,且至多一条边两个点都在点集中
找出一个 lenient点覆盖
范围
t 1e4
n 1e6
5s
512MB
我的思路
首先 如果能黑白染色,成功,那么也就是每个边一端黑一端白, 全选黑或全选白都是一个答案
如果 黑白染色出现冲突,那么这两个点一定在一个奇环上
也就是这个奇环上存在两个点都是黑色, 最可以先把这个环上的边全部当作不存在,重新做染色,如果能成功, 计算这个环上同一个并查集点的颜色关系,
如果两两都不在同一个集合中那么说明拆了环都是独立的部分,那么任意染黑白即可
如果存在 a—–b 同集合中
a,b 同色 , [a..b]个数奇数的一半一定是黑白间隔
a,b 异色 , [a..b]个数偶数的一半一定是黑白间隔
换句话说, 其实原图去掉那个两个点都在集合中的边, 剩下的满足黑白染色,现在则是看哪些确定可以连起来
过程中检查冲突
如果剩余还有没连的 任选一个作为分割即可
但是 实现上能找环但如何找奇环
独立染色可以写,但合并时如何实现?
题解
前面几段和我想的一样, 奇偶黑白染色, 也就是需要在奇数环上剪断一条边,让整个染色合法
这里主要是 对无向图做dfs建立树
那么出现环的时候就是子节点指向父节点的时候
我们在dfs过程中黑白染色,那么出现回边时根据染色就可以知道它是奇环还是偶环,
如果我们统计了每条边出现在我们找到的奇环上的次数,和偶环上的次数,那么 如果一条边出现在奇数环上次数等于所有奇环次数,偶数环次数为零,那么删除这条边即可(可能有多个满足,任意删除一条)
// 必要性proof见下面, 充分显然
所以接下来就是当发生回环时,如何统计边在奇环偶环上出现次数了,如果直接对边计数,那么复杂度就过不了
树上差分, cnt[id]表示边id到根的所有边都 进行了+cnt[id],这样 当有点u到点v的回边时,就 cnt[faedge[u]]++,cnt[faedge[v]]–, 对于不在树上的回边edge[id] = {u,v}
不需要差分直接统计, cnt[id]++
最后统计完后整理具体次数
然后找满足的边拆掉,再染色即可(注意拆掉边两端需要是黑色
性质证明
这里 显然的是 如果是两端同色的点, 那么它一定在所有奇环中,不在所有偶环中
也就是必要性显然
如果我们枚举了所有的环,那么拆掉它,所有奇数环也被拆掉了, 所以充分性也成立
问题是上面的实现 并没有枚举所有的环,枚举的只是树边+一条回边的所有环, 而环可能是由多条回边构成的
引理1: 如果环A和环B的一部分拼成环C,那么ABC中要么全是偶环,要么其中两个是奇环,
(这里拼成的意思是 A 和 B 有共用的一条链, C= (A-共用链)+(B-共用链)
那么要证明的是两部分, 这个两端同色的边也在未统计到的多回边的奇数环中,不在未统计到的多回边偶数环中
如果它(两端同色的边)不在未统计到的多回边奇数环中
那么这个环H(奇,回边=n) 可以拆成一个H1(奇,回边n-1) + H(偶,回边1)
因为H(偶,回边1) 我们一定计算到了, 只能递归下降, 且不会在 它们两的重复边上,因为它不在偶环上
那么这个环H(奇,回边=n) 可以拆成一个H1(偶,回边n-1) + H(奇,回边1)
因为H(奇,回边1) 我们一定计算到了 所以它在奇数环中
综上它一定在 未统计到的多回边奇数环中
如果它在未统计到的多回边偶数环中
那么这个环H(奇,回边=n) 可以拆成一个H1(偶,回边n-1) + H(偶,回边1)
它一定不在 H(偶,回边1) 中, 所以递归下降,且它也不在 两个环共用的边上
那么这个环H(偶,回边=n) 可以拆成一个H1(奇,回边n-1) + H(奇,回边1)
注意到上述结论, 这个边一定在这两个环里都有,因此这个边在它们重复的边上而不在偶环里
因此 得证
代码
https://codeforces.com/contest/1680/submission/158000410
1 |
|
总结
知识点
无向图 = dfs -> 树+回边
而一部分无向图的环 = 多个树边+一条回边? 也可能由回边组成的环
树上差分 = 记录当前点到根的所有边的统一操作,如+1/-1
学了一手fill()
函数,看起来很好用啊
然后 无向图 树上dfs, 的父边而不是父点 dfs(int u,int fe /*father edge*/)
参考
csdn 修复了一些越界和等式操作, 修改了部分变量和包裹逻辑,整体