對於一個無向圖 $G$,三元組 $(a, b, c)$ 被稱爲優秀的當且僅當知足以下條件:node
$1. a < b < c$;c++
$2. a $ 與 $b$ 有邊相連;git
$3. a $ 與 $c$ 有邊相連;算法
$4. b$ 與 $c$ 沒有邊相連。ide
如今有一個 $n$ 個點的連通無向圖 $G$,每次找一個優秀的三元組 $(a, b, c)$ 將 $b$ 和 $c$ 連邊,若是沒有則結束加邊過程。spa
問最終獲得的圖有多少種用 $n$ 種顏色對點染色的方案,對 $998244353$ 取模後輸出。code
一種染色方案合法當且僅當每一個點顏色是 $1$ 到 $n$ 中的一個,而且一條邊兩端的點顏色不一樣。blog
對於一個無向圖 $G$,三元組 $(a, b, c)$ 被稱爲優秀的當且僅當知足以下條件:get
$1. a < b < c$;it
$2. a $ 與 $b$ 有邊相連;
$3. a $ 與 $c$ 有邊相連;
$4. b$ 與 $c$ 沒有邊相連。
如今有一個 $n$ 個點的連通無向圖 $G$,每次找一個優秀的三元組 $(a, b, c)$ 將 $b$ 和 $c$ 連邊,若是沒有則結束加邊過程。
問最終獲得的圖有多少種用 $n$ 種顏色對點染色的方案,對 $998244353$ 取模後輸出。
一種染色方案合法當且僅當每一個點顏色是 $1$ 到 $n$ 中的一個,而且一條邊兩端的點顏色不一樣。
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e6+5,p=998244353; int n,m,rt[N],fa[N],cnt,tot,head[N],ne[N<<1],to[N<<1],ans=1; struct node{ int x,l,r,num; }t[N*21]; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } il void ins(int x,int y){ ne[++tot]=head[x]; head[x]=tot;to[tot]=y; } il int getfa(int x){ return fa[x]?(fa[x]=getfa(fa[x])):x; } il void update(int x){ t[x].num=t[t[x].l].num+t[t[x].r].num; } il void insert(int &x,int l,int r,int pos){ if(!x)x=++cnt; if(l==r){t[x].num=1;return;} int mid=(l+r)>>1; if(pos<=mid)insert(t[x].l,l,mid,pos); else insert(t[x].r,mid+1,r,pos); update(x); } il void merge(int &x,int y,int l,int r){ if(!x||!y){x=x+y;return;} if(l==r){t[x].num=1;return;} int mid=(l+r)>>1; merge(t[x].l,t[y].l,l,mid); merge(t[x].r,t[y].r,mid+1,r); update(x); } il int query(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return t[x].num; int mid=(l+r)>>1;int res=0; if(ql<=mid)res=query(t[x].l,l,mid,ql,qr); if(mid<qr)res+=query(t[x].r,mid+1,r,ql,qr); return res; } int main() { n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); ins(x,y);ins(y,x); insert(rt[min(x,y)],1,n,max(x,y)); } for(int i=1;i<=n;i++){ int f1=getfa(i); for(int j=head[i];j;j=ne[j]){ int f2=getfa(to[j]); if(to[j]<i&&(f2^f1))merge(rt[f1],rt[f2],1,n),fa[f2]=f1; } ans=1ll*ans*(n-query(rt[f1],1,n,i+1,n))%p; } printf("%d\n",ans); return 0; }