[ABC294Ex] K-Coloring

考虑 dfs 后搞出 dfs 树,考虑若干返祖边有限制,那么,我们一个朴素的想法是枚举这些有被返祖边搞到的点的颜色,但这样最坏是 O(Kn) 的。

但显然一条返祖边在钦定完一个端点的颜色之后,另一端的颜色便可以不用钦定,因此指数可以减小一点。

那么我们可以钦定每个返祖边深度小的点的颜色,但是直接钦定是 O(Kt) 的,t 是返祖边深度小的点的集合大小。考虑我们并不关心其真正的颜色是什么,因此这东西可以集合划分后再给每个集合分配颜色。

那么这样子,你就有若干点的颜色钦定了,记钦定的颜色数量为 c,但整棵树的染色显然不可能只用 c 种,但其他的颜色我们都是未钦定的,考虑另分一类给这些颜色。

f(x,i) 表示 x 为第 i 种颜色的时候,其子树内染色的方案数。

考虑转移,对于树边的转移是朴素的。

对于返祖边的话,由于我们已经钦定了深度小的点的颜色,那么当前点的颜色也必须与其相同,不相同的方案数直接没了即可。

注意之后方案数应乘上对该集合划分分配颜色的方案数。

不重不漏的证明:考虑一种合法的染色方案,显然会被在钦定其返祖点的颜色时钦定到这种方案,且只钦定到一次。假如一种方案被钦定了两次的话。若颜色划分的集合不同,那么两种染色方案一定不同。若颜色划分的集合相同,但对集合分配的颜色方案不同,则两种染色方案一定不同。则关键,在于转移。而我们的转移并不会重算同一种方案,因为其都是子树各自考虑而又独立合并的。所以一种方案不会被钦定多次。

#include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; const int mod=998244353; struct edge { int nex,to; }e[70]; int f[35][35],n,m,K,dfn[35],tot,otot,o[35],rt,col[35],fa[35],hea[35],cnt=1; void add_edge(int x,int y) { e[++cnt].nex=hea[x]; e[cnt].to=y; hea[x]=cnt; } void dfs0(int x,int pre) { dfn[x]=++tot; for(int i=hea[x];i;i=e[i].nex) { if((i==(pre^1))) continue ; int y=e[i].to; if(!dfn[y]) dfs0(y,i); else if(dfn[y]<=dfn[x]) { o[++otot]=y; } } } bool vis[35]; int C; void dp(int x,int pre) { if(!col[x]) { for(int i=0;i<=C;i++) f[x][i]=1; } else { for(int i=0;i<=C;i++) f[x][i]=0; f[x][col[x]]=1; } vis[x]=1; // cout<<x<<" "<<ff<<" in\n"; for(int j=hea[x];j;j=e[j].nex) { if((j==(pre^1))) continue ; int y=e[j].to; if(!vis[y]) { dp(y,j); int qwq=f[y][0]*(K-C-1)%mod; for(int i=1;i<=C;i++) qwq=(qwq+f[y][i])%mod; f[x][0]=f[x][0]*qwq%mod; qwq=0; for(int i=1;i<=C;i++) qwq=(qwq+f[y][i])%mod; for(int i=1;i<=C;i++) { int qaq=(f[y][0]*(K-C)%mod+(qwq-f[y][i]+mod)%mod)%mod; f[x][i]=f[x][i]*qaq%mod; } } else if(dfn[y]<=dfn[x]) { for(int i=0;i<=C;i++) { if(i==col[y]) f[x][i]=0; } } } // cout<<": "<<x<<" -> "<<col[x]<<'\n'; // for(int i=0;i<=C;i++) cout<<f[x][i]<<' '; // cout<<'\n'; } int nwans,ans; void dfs(int x,int c) { if(c>K) return ; if(x==otot+1) { for(int i=1;i<=n;i++) vis[i]=0; C=c; dp(rt,0); int res=f[rt][0]*(K-C)%mod; for(int i=1;i<=C;i++) res=(res+f[rt][i])%mod; for(int i=K-C+1;i<=K;i++) res=res*i%mod; nwans=(nwans+res)%mod; return ; } for(int i=1;i<=c;i++) col[o[x]]=i,dfs(x+1,c); col[o[x]]=c+1; dfs(x+1,c+1); } signed main() { cin.tie(0); ios::sync_with_stdio(false); cin>>n>>m>>K; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; add_edge(x,y); add_edge(y,x); } ans=1; for(int i=1;i<=n;i++) { if(!dfn[i]) { rt=i; nwans=0; otot=0; dfs0(rt,0); sort(o+1,o+1+otot); if(otot) otot=unique(o+1,o+1+otot)-o-1; // for(int j=1;j<=otot;j++) cout<<o[j]<<' '; // cout<<'\n'; dfs(1,0); // cout<<nwans<<'\n'; ans=ans*nwans%mod; } } ans=(ans%mod+mod)%mod; cout<<ans; return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/17236869.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2022-03-20 P6619 [省选联考 2020 A/B 卷] 冰火战士
2022-03-20 D - Prefix XORs
点击右上角即可分享
微信分享提示