之前我们暴力枚举路径上的边每次要ON的复杂度太慢了。
考虑我们每次找路径是找自底向上找,,很多次会找到非桥边,造成不必要的浪费步数。
所以我们可以用并查集来压缩路径。
若点x与其父亲的路径从桥边变成非桥边,则把x指向y的祖宗。
这样就能跳过非桥边进行无意义的访问了。
单次复杂度将为logn
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 4e5+7;
int head[M],cnt=1,head_c[M],cnt_c=1;
struct EDGE{int to,nxt,w;}ee[M*2],ee_c[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
void add_c(int x,int y,int w){ee_c[++cnt_c].nxt=head_c[x],ee_c[cnt_c].w=w,ee_c[cnt_c].to=y,head_c[x]=cnt_c;}
int dfn[M],low[M],nm;
bool bridge[M];
void tarjan(int x,int in_edge)
{
dfn[x]=low[x]=++nm;
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(!dfn[y])
{
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])bridge[i]=bridge[i^1]=t