【题意】
给出一个有n个点的无向图,其中有n-1条主要边且这些主要边构成一棵树,此外还有m条其他边,求斩断原图的一条主要边和一条其他边使得图不连通的方案数。
注意,即使只斩断主要边就可以使得原图不连通,你仍然需要继续斩断一条其他边才能成为一种方案。
【解法】
考虑到原图的一个性质:使得原图不连通的方案只有以下两种情况:
1.主要边是原图的桥
2.主要边和附加边连接的两个连通块只有这两条边相连
显然每个1产生的方案都有m种,每个2产生的方案只有一种。
考虑到原图的主要边构成一棵树并且只有主要边可能是桥,因此想到一个性质:
如果把每条附加边两端点在树上的路径进行标记,那么没有被标记过的边就是原图的桥(注意这里桥一定是主要边),只被标记过一次的边一定对应唯一的一个2。
因此考虑使用树链剖分,再加上区间修改功能,最后查询每条边被标记的次数,那么没有被标记的边就是原图的桥,ans+=m(因为这条边和任意一条附加边组合都是一种方案);只被标记了一次的边对应唯一的一个2,ans++;被标记超过1次的边显然是不能构成方案的(因为砍断它之后它两边对应的两个连通块至少有两条边相连,砍断其中的任意一条边是无法使两个连通块断开的)。
顺便一提,实现区间修改单点查询功能可以使用差分数组,这样单次区间修改O(1),最后逐个查询O(n),再加上树剖单次路径修改O(logn)次,树剖预处理O(n),总的复杂度为O(n+mlogn),比起线段树单次路径修改O(log2n),总复杂度O(nlogn+mlog2n)快了很多,并且代码也更短,常数更小,也很省内存。
【后记】
听出题人(magic_sheep)说本题有好几种解法,然而本鶸渣只想到了一种,其他的还没想出来,在此膜拜神犇。
这个解法的桥和连通块听上去很像图论有关内容,实际上这个树剖解法就是从图论上的桥和连通块发展来的,只不过利用了树的性质,采用树剖实现。因此,我觉得求桥和双连通分量的算法稍加组合和改造应该也是可以解决本题的。
感觉本题很有思想难度,但代码实现却非常容易(我的代码仅仅80+行)。多做做这种题,很有意义。
【8.16增加】
昨天和ad神犇讨论了一下,ad神犇说这个题的路径处理部分不需要树剖,直接用树上差分就行。
具体做法就是把两点那个地方的差分数组++,把LCA那里的差分数组-=2(因为要屏蔽LCA),最后采用一遍dfs或者bfs之后按照bfs逆序处理就行。
LCA可以用Tarjan事先求出,这样LCA的复杂度就是O(n),单次路径处理的复杂度也从O(logn)降到了O(1)。
学到了%%%