转化一下题意,m条边只有一段时间出现在图中。
可以线段树分治+并查集维护,并查集要按秩合并因为要支持撤销
Code
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iostream>
#include <unordered_map>
#define rint register int
#define L (rt*2)
#define R (rt*2+1)
using namespace std;
const int maxn=1e5+5;
const int M=1e9+7;
struct Node{
int x;
int fa_x,siz_x,rk_x;
}a[maxn*2];
int n,m,tot;
int op[maxn],x[maxn],y[maxn],del_time[maxn];
int ny[maxn],fa[maxn],siz[maxn],rk[maxn];
unordered_map < long long,int > app;
vector < pair<int,int> > vec[maxn*4];
char buf[1<<20],*p1,*p2;
#define gc() (p1==p2?(p2=buf+fread(p1=buf,1,1<<20,stdin),p1==p2?EOF:*p1++):*p1++)
#define read() ({
rint x=0;register bool f=0;register char ch=gc();
while(ch<'0'||ch>'9') f|=ch=='-',ch=gc();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch&15),ch=gc();
f?-x:x;
})
void pre(){
for(int i=1;i<=n;++i) fa[i]=i,siz[i]=1;
ny[1]=1;
for(int i=2;i<=n;++i) ny[i]=1ll*(M-M/i)*ny[M%i]%M;
}
void modify(int rt,int l,int r,int ql,int qr,int x,int y){
if(ql<=l&&r<=qr) return vec[rt].push_back(make_pair(x,y)),void();
int mid=(l+r)/2;
if(ql<=mid) modify(rt*2,l,mid,ql,qr,x,y);
if(qr> mid) modify(rt*2+1,mid+1,r,ql,qr,x,y);
}
int find(rint x){
while(fa[x]!=x) x=fa[x];
return x;
}
void merge(rint x,rint y){
a[++tot]=(Node){x,fa[x],siz[x],rk[x]};
a[++tot]=(Node){y,fa[y],siz[y],rk[y]};
if(rk[x]==rk[y]) rk[y]++;
if(rk[x]>rk[y]) swap(x,y);
fa[x]=y,siz[y]+=siz[x];
}
void solve(int rt,int l,int r,int ans){
rint tmp=tot;
for(rint i=0;i<(int)vec[rt].size();++i){
const rint xx=find(vec[rt][i].first),yy=find(vec[rt][i].second);
if(xx==yy) continue;
ans=1ll*ans*ny[siz[xx]]%M*ny[siz[yy]]%M*(siz[xx]+siz[yy])%M;
merge(xx,yy);
}
if(l==r) printf("%d
",ans);
else{
rint mid=(l+r)/2;
solve(rt*2,l,mid,ans),solve(rt*2+1,mid+1,r,ans);
}
while(tot>tmp){
const rint xx=a[tot].x;
const rint ff=a[tot].fa_x;
const rint ss=a[tot].siz_x;
const rint rr=a[tot].rk_x;
fa[xx]=ff,siz[xx]=ss,rk[xx]=rr;
--tot;
}
}
int main(){
freopen("geography.in","r",stdin);
freopen("geography.out","w",stdout);
n=read(),m=read();
pre();
for(rint i=1;i<=m;++i){
op[i]=read(),x[i]=read(),y[i]=read();
if(x[i]>y[i]) swap(x[i],y[i]);
const long long hh=1ll*x[i]*n+y[i];
if(op[i]==1){
app[hh]=i;
del_time[i]=m;
continue;
}
else del_time[app[hh]]=i-1;
}
for(rint i=1;i<=m;++i) if(del_time[i]) modify(1,1,m,i,del_time[i],x[i],y[i]);
solve(1,1,m,1);
return 0;
}