【题目】BZOJ-2560 串珠子

探讨使用图论与动态规划解决特定类型的连通图方案数问题,通过定义f[s]、g[s]和h[s]来计算使图连通的边方案数,避免重复计算并确保所有点连通。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

nnn个结点,编号111nnn。可以在当中连边,点i,ji,ji,j之间可以连ci,jc_{i,j}ci,j种颜色的边,且每对点之间最多连一条边。求使得整个图连通的连边方案数(边的颜色不同算作不同方案)。答案模100000000710000000071000000007

8⩽n⩽168\leqslant n\leqslant 168n16n∈Zn\in ZnZ


思路

f[s]f[s]f[s]表示将集合sss中的点连边,使得这些点连通的方案数。容易想到把集合sss分成两个小集合s1,s2s_1,s_2s1,s2,用两个小的状态更新当前状态。然而这样有几个问题:

  1. 两个小集合内的点不一定是连通的。
  2. 同一种方案可能有多种划分的方式,方案会算重。
  3. 状态转移需要在这两个小集合之间连边,连边的方案数很难处理。

正难则反,设g[s]g[s]g[s]表示将集合sss中的点连边,使得这些点不连通的方案数,h[s]h[s]h[s]表示任意连边的方案数,则有f[s]=h[s]−g[s]f[s]=h[s]-g[s]f[s]=h[s]g[s]。由于每条边都有ci,j+1c_{i,j}+1ci,j+1种选择(连ci,jc_{i,j}ci,j种颜色的边以及不连边),可以得到h[s]h[s]h[s]的表达式:

h[s]=∏i,j∈s(c[i][j]+1)h[s]=\prod_{i,j\in s}(c[i][j]+1)h[s]=i,js(c[i][j]+1)

下面要求g[s]g[s]g[s],容易想到把集合sss分成两个小集合s1,s2s_1,s_2s1,s2,用两个小的状态更新当前状态。然而这样有几个问题:

  1. 两个小集合内的点不一定是不连通的。
  2. 同一种方案可能有多种划分的方式,方案会算重。

这个时候就不能正难则反了,要敢于直面惨淡的人生
既然sss中的点不连通,那么一定可以从其中选出一个连通的部分出来(设为s1s_1s1),而另一部分连不连通不重要,因为这两部分中间没有连边,整个图一定是不连通的。可以初步写出递推式:

g[s]=∑s1∪s2=sf[s1]⋅h[s2]g[s]=\sum_{s_1\cup s_2=s}f[s_1]\cdot h[s_2]g[s]=s1s2=sf[s1]h[s2]

但是方案数依然会算重,因为同一种方案中有多个连通块可以当做s1s_1s1。解决方法很简单,在集合sss中任选一个点kkk,枚举s1s_1s1的时候保证k∈s1k\in s_1ks1,就不会多解;s1s_1s1的大小是任意的,所以也不会漏解。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值