【JZOJ6389】小w学图论

description

小w这学期选了门图论课,他在学习点着色的知识。他现在得到了一张无向图,并希望在这张图上使用最多n种颜色给每个节点染色,使得任意一条边关联的两个节点颜色不同。
小w获得一张n个节点m条边的基图,并得到了一份神秘代码。他会根据这份代码的内容构建完整的无向图。
while(1){
int modify_tag=0;
for(int x=1;x<=n;x++)
for(int y=x+1;y<=n;y++)
for(int z=y+1;z<=n;z++)
if(edge(x,y)∈G && edge(x,z)∈G){
add edge(y,z) to G
modify_tag=1;
}
if(modify_tag==0) break;
}

即对于图上的任意三元组x<y<z,若(x,y),(x,z)在图中则在图上加上一条(y,z)的边,直至无法加边为止。
小w想要知道使用n种颜色给这张基图生成的完整无向图的染色方案数。小w太菜了,他无力解决这个难题,于是只好把它交给了你。


analysis

  • 首先有一个结论,ans=∏n−g[i]ans=\prod n-g[i]ans=ng[i]g[i]g[i]g[i]表示与iii相连、编号比iii大的节点数量

  • 如果从大到小染色染到第iii位,g[i]g[i]g[i]已经染过色了且iii点和这g[i]g[i]g[i]个点构成完全图

  • 那么这g[i]g[i]g[i]个点颜色都不相同,iii位染色的方案数就是n−g[i]n-g[i]ng[i],以此类推

  • 暴力做法是O(n2)O(n^2)O(n2)把这个图建出来,搞出每一个g[i]g[i]g[i],全部乘起来

  • 其实可以考虑维护nnn棵线段树,存储第iii位向后的连边情况

  • 编号从小到大合并,假设合并到第kkk位,区间查询比kkk大有多少已经连边的点,乘进答案

  • 然后再找出比kkk大且最小的存在的编号,把kkk的线段树合并到该编号的线段树就可以了

  • 也可以用setsetset维护连点的集合,合并两集合就启发式合并,但这个我还不是很懂


code

线段树合并

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define MAX MAXN*50
#define ha 998244353
#define ll long long
#define reg register ll
#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值