一、题目
二、解法
0x01 点双联通分量
环的问题可以用联通分量来做,对于一个联通分量内如果边数等于点数,那么里面的边都是合法答案,否则每一条边一定被两个环覆盖。然后因为边双处理不了如下图的情况,所以我们使用点双来缩点。
但是不能使用常规的点双,因为我们需要枚举每个联通分量的边,而割点可能在多个联通分量中,所以疯狂枚举割点连出去的边就会超时。我百思不得其解,借鉴了题解的做法,我们可以在 t a r j a n tarjan tarjan的时候把边和点都记录下来,用 s e t set set去重即可。
0x02 树上差分
利用了一个结论:如果两个环有相交,那么就会生成一个新的环(证明:去掉相同的部分,把不同的部分拼一起)
建出生成树,所以对于树上的边,如果他要成为答案,它们只能被标记一次,对于非树边,它树上路径上的所有边如果只被标记一次,那么他就是答案。打标记就用树上差分就行了,好像还要写 l c a lca lca
下面给出第一种做法的代码。
#include <cstdio>
#include <iostream>
#include <set>
using namespace std;
const int M = 100005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9')