失智
又被题目吓到了
考虑树的情况,连通块数目就是总点数-存在的边。
考虑仙人掌的情况,连通块数目就是总点数-存在的边+存在的环
因为是0/1分开考虑,所以所谓存在的X就是要求相关联的点颜色一样。
使用lct维护圆方树就可以了。
算一个环都变黑的概率可以容斥,因为总环中点数是不超过n+m的,暴力就可以了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int mo = 998244353,N=4e5+10;
typedef long long ll;
int n,m,t,w;
ll jc[N],njc[N],ans;
int fa[N],c[N][2],tot,rtag[N],s[N],sv[N];
#define isroot(x) (c[fa[x]][0]!=(x)&&c[fa[x]][1]!=(x))
#define lr(x) (c[fa[x]][1]==(x))
#define upd(x) (s[x]=s[c[x][0]]|s[c[x][1]]|sv[x])
ll C(ll n,ll m) {
if (n<m) return 0; return jc[n] * njc[m] % mo * njc[n-m] % mo;
}
ll ksm(ll x,ll y) {
x%=mo;
ll ret = 1; for (;y;y>>=1) {
if (y&1) ret=ret*x%mo;
x=x*x%mo;
}
return ret;
}
void rotate(int x) {
int y=fa[x],z=lr(x);
c[y][z]=c[x][1-z];
if (c[x][1-z]) fa[c[x][1-z]]=y;
if (!isroot(y)) c[fa[y]][lr(y)]=x;
fa[x]=fa[y];
fa[y]=x;
c[x][1-z]=y;
upd(y);
}
void rev(int x){
if (x){
rtag[x]^=1;swap(c[x][0],c[x][1]);
}
}
void down(int x){
if (rtag[x]){
rtag[x]=0;
rev(c[x][0]),rev(c[x][1]);
}
}
int Q[N];
void splay(int x) {
int t=x; while (!isroot(t)) Q[++Q[0]]=t,t=fa[t];
Q[++Q[0]]=t; while (Q[0]) down(Q[Q[0]--]);
while (!isroot(x)) {
if (!isroot(fa[x])){
if (lr(x)==lr(fa[x])) rotate(fa[x]); else rotate(x);
}
rotate(x);
}
upd(x);
}
void access(int x) {
for (int u=0;x;u=x,x=fa[x]){
splay(x);
c[x][1]=u;
upd(x);
}
}
void mkroot(int x) {
access(x),splay(x),rev(x);
}
void link(int x,int y){
mkroot(x),access(x),splay(x);
fa[x]=y;
}
void cut(int x,int y) {
mkroot(x),access(y),splay(y);
c[y][0]=0,fa[x]=0;
upd(y);
}
bool cnet(int x,int y) {
mkroot(x);
splay(x);
access(y),splay(y);
return !isroot(x);
}
ll ds,ed,cir,invn,eee;
ll lis[N];
void go(int x) {
if (!x) return;
down(x); go(c[x][0]);
lis[++lis[0]]=x;
go(c[x][1]);
}
ll calcBlackCir(int sz) {
ll ret = 0;
for (int i = 0; i <= sz; i++) {
ret = (ret + ((i&1) ? -1 : 1) * C(sz, i) * ksm((n-i) * invn % mo,t) % mo) % mo;
}
return ret;
}
int main() {
freopen("cactus.in","r",stdin);
freopen("cactus.out","w",stdout);
n=1e5,jc[0]=1; for (int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mo;
njc[n]=ksm(jc[n],mo-2); for (int i=n-1;~i;i--)njc[i]=njc[i+1]*(i+1)%mo;
scanf("%d %d %d %d",&n,&m,&t,&w); tot=n;
invn = ksm(n, mo - 2);
ds = (w==0) ? n * ksm((n-1)*invn%mo,t) % mo : n;
for(int ee=1;ee<=m;ee++){eee=ee;
int u,v; scanf("%d %d",&u,&v);
int flag=1;
if (cnet(u,v)) {
mkroot(u),access(v),splay(v);
if (s[v]==0) {
lis[0]=0;
go(v);
cir = (cir + ksm((n - lis[0]) * invn % mo, t)) % mo;
if (w) cir = (cir + calcBlackCir(lis[0])) % mo;
tot++; sv[tot]=1; upd(tot);
for (int i = 1; i < lis[0]; i++) {
cut(lis[i],lis[i+1]);
link(lis[i],tot);
}
link(lis[lis[0]],tot);
} else {
flag=0;
}
} else link(u,v);
if (flag) {
ed = (ed + ksm((n-2) * invn % mo, t))%mo;
if (w) ed = (ed + 1 - 2*ksm((n-1)*invn%mo, t) + ksm((n - 2)*invn%mo, t))%mo;
}
printf("%lld\n",((ds-ed+cir)%mo+mo)%mo);
}
}