[ACM] 树/图上经典题

poj 3694 Network

题意:给你一个无向连通图,然后q次操作,每次在图上添加一条边,每添加一条边,输出一次图上桥的数量。点数1e5,边数2e5,q为1e3。

看完题,发现做这道题需要先掌握tarjan算法。显然,整个图可以分解为多个边双连通分量组成的一个树,那么桥的个数就是树的边数。对于每次操作,如果添加的边连接了同一个边双连通分量中的两个点,则不会改变树的结构,所以,问题转化成为了添加的边连接了不同边双连通分量中的两个点u和v,应该怎么办。注意到边双连通分量组成了一棵树,连接u和v之后,必然形成一个环,显然,新形成的环导致了一个新的边双连通分量产生,也就是说,原来的几个双连通分量,融合成了一个双连通分量,或者说原来树上的几个点,缩成了一个新的点。那么新的点是原来树上的哪些点形成的呢?在纸上画一画就能发现,新的点由原来u到v的路径上的所有点形成。至此,问题简化成为了:给你一棵树,每条边边权初始为1,每次操作将树上一条路径上的所有边,边权置为0,然后求整棵树的边权和。

简化完之后,有两种做法。第一种是显而易见的树链剖分,但树链剖分代码繁琐,此处建议使用第二种做法:

由于缩点是不可逆的,也就是说对于某些点,一旦将它们缩成了一个新点,那么这些点就绝不会再访问到了。对应到简化的问题中,一旦将某条路径上所有边的边权置为0,那么之后计算整棵树的边权和的时候,就再不用考虑这些点了。因此我们有一个做法,每次操作u到v的路径时,先计算u到v的lca,然后暴力地把u到v路径上的所有边边权置为0,同时每访问到路径上的一个点,将这个点的父节点指向lca(u, v),因为如之前所述,这些点不会再被用到了。

最后计算第二种做法的时间复杂度,求边双连通分量时间O(n + m),之后的操作,求lca建议使用暴力做法,由于一个点至多被访问一次,因此时间复杂度为O(n),总时间复杂度O(n + m)。

你可能感兴趣的:(算法/数据结构)