@atcoder - CODE FESTIVAL 2017 Elimination Tournament Round 3 F@ Unicyclic Graph Counting
@description@
求有多少 n 点 n 边的无向连通图,满足第 i 个点的度数为 \(d_i\)。
@solution@
如果是树显然就 prufer 定理;基环树就考虑拓展一下。
枚举环上的点集合 S,则环内部能够连出的方案数为 \(\frac{(|S| - 1)!}{2}\)(注意环的大小 \(|S| \geq 3\))。
接着,将环缩成一个新点 x',则它的度数为 \(d_{x'} = \sum_{i\in S}(d_i - 2)\)(注意 \(d_i \geq 2\))。
对缩点后的新图运用 prufer 定理,得到:
\]
不过 x' 的出边并不是全部相同。对于 x' 还有个系数 \(\frac{(\sum_{i\in S}(d_i - 2))!}{\prod_{i\in S}(d_i - 2)!}\),表示邻接边的分配方案。
因此整合得到:
&\frac{(|S| - 1)!}{2}\times \frac{(n - |S| - 1)!}{(\sum_{i\in S}(d_i - 2) - 1)!\times \prod_{i\not \in S}(d_i - 1)!}\times \frac{(\sum_{i\in S}(d_i - 2))!}{\prod_{i\in S}(d_i - 2)!}\\
=&\frac{(|S| - 1)!}{2}\times \frac{(n - |S| - 1)!}{\prod_{i}(d_i - 1)!}\times (\sum_{i\in S}(d_i - 2)) \times \prod_{i\in S}(d_i - 1)
\end{aligned}
\]
把 \((|S|, \sum(d_i - 2))\) 当作状态做一个 O(n^3) 的 dp 求 \(\prod_{i\in S}(d_i - 1)\) 即可。
特判 n 个点连成一个大环的情况。
@accpeted code@
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 300;
const int MOD = int(1E9) + 7;
const int INV2 = (MOD + 1) / 2;
inline int add(int x, int y) {return (x + y >= MOD ? x + y - MOD : x + y);}
inline int sub(int x, int y) {return (x - y < 0 ? x - y + MOD : x - y);}
inline int mul(int x, int y) {return 1LL * x * y % MOD;}
int pow_mod(int b, int p) {
int ret = 1;
for(int i=p;i;i>>=1,b=mul(b,b))
if( i & 1 ) ret = mul(ret, b);
return ret;
}
int fct[2*MAXN + 5], ifct[2*MAXN + 5];
void init() {
fct[0] = 1; for(int i=1;i<=2*MAXN;i++) fct[i] = mul(fct[i - 1], i);
for(int i=0;i<=2*MAXN;i++) ifct[i] = pow_mod(fct[i], MOD - 2);
}
int dp[2][MAXN + 5][MAXN + 5];
int d[MAXN + 5], N;
int main() {
init(), scanf("%d", &N);
for(int i=1;i<=N;i++)
scanf("%d", &d[i]), d[i]--;
int tot = 0; dp[0][0][0] = 1;
for(int i=1;i<=N;i++) {
if( d[i] ) {
for(int j=0;j<i;j++)
for(int k=0;k<=tot;k++)
dp[1][j][k] = dp[0][j][k];
for(int j=0;j<i;j++)
for(int k=0;k<=tot;k++)
dp[0][j+1][k+d[i]-1] = add(dp[0][j+1][k+d[i]-1], mul(d[i], dp[1][j][k]));
tot += d[i] - 1;
}
}
int ans = mul(mul(fct[N-1], INV2), dp[0][N][0]), tmp = 1;
for(int i=1;i<=N;i++) tmp = mul(tmp, ifct[d[i]]);
for(int i=3;i<N;i++)
for(int j=1;j<=tot;j++) {
int coef = mul(mul(fct[i-1], INV2), mul(fct[N-i-1], tmp));
ans = add(ans, mul(mul(coef, j), dp[0][i][j]));
}
printf("%d\n", ans);
}
@details@
如果是不带度数限制基环树,还是用的 prufer 序列,和上述方法相同(貌似矩阵树解不了的样子。。。)
本题还有一个更快的 O(n^2) 做法:
&\frac{(|S| - 1)!}{2}\times \frac{(n - |S| - 1)!}{(\sum_{i\in S}(d_i - 2) - 1)!\times \prod_{i\not \in S}(d_i - 1)!}\times \frac{(\sum_{i\in S}(d_i - 2))!}{\prod_{i\in S}(d_i - 2)!}\\
=&\frac{(|S| - 1)!\times (n - |S| - 1)!}{2}\times \frac{\sum_{i\in S}(d_i - 2)}{\prod_{i\not \in S}(d_i - 1)!\prod_{i \in S}(d_i - 2)!}\\
=&\frac{(|S| - 1)!\times (n - |S| - 1)!}{2}\times \sum_{i\in S}\frac{1}{\prod_{j\not \in S}(d_j - 1)!\times \prod_{j \in S, j\not = i}(d_j - 2)!\times (d_i - 3)}
\end{aligned}
\]
只需要存状态 \(|S|\) 以及是否贡献了 \(\frac{1}{d_i - 3}\)。一样需要特判。
@atcoder - CODE FESTIVAL 2017 Elimination Tournament Round 3 F@ Unicyclic Graph Counting的更多相关文章
- [AtCoder Code Festival 2017 QualB D/At3575] 101 to 010 - dp
[Atcoder Code Festival 2017 QualB/At3575] 101 to 010 有一个01序列,每次可以选出一个101,使其变成010,问最优策略下能操作几次? 考虑像 11 ...
- Atcoder CODE FESTIVAL 2017 qual B D - 101 to 010 dp
题目链接 题意 对于一个\(01\)串,如果其中存在子串\(101\),则可以将它变成\(010\). 问最多能进行多少次这样的操作. 思路 官方题解 转化 倒过来考虑. 考虑,最终得到的串中的\(' ...
- 题解【AtCoder - CODE FESTIVAL 2017 qual B - D - 101 to 010】
题目:https://atcoder.jp/contests/code-festival-2017-qualb/tasks/code_festival_2017_qualb_d 题意:给一个 01 串 ...
- 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数
蒟蒻__stdcall终于更新博客辣~ 一下午+一晚上=一道计数题QAQ 为什么计数题都这么玄学啊QAQ Prelude 题目链接:这里是传送门= ̄ω ̄= 下面我将分几个步骤讲一下这个题的做法,大家不 ...
- AtCoder Code Festival 2017 Team Relay J - Indifferent
题目大意:共$2n$个价格$p_i$.两人轮流取.你每次取最大的,对方每次随机取.问你取的期望和是多少. 题解:从小到大排序,$\sum\limits_{i=0}^{2n-1} \frac{i*p_i ...
- atcoder/CODE FESTIVAL 2017 qual B/B(dfs染色判断是否为二分图)
题目链接:http://code-festival-2017-qualb.contest.atcoder.jp/tasks/code_festival_2017_qualb_c 题意:给出一个含 n ...
- Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分
题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...
- Atcoder CODE FESTIVAL 2017 qual C C - Inserting 'x' 回文串
题目链接 题意 给定字符串\(s\),可以在其中任意位置插入字符\(x\). 问能否得到一个回文串,若能,需插入多少个\(x\). 思路 首先统计出现次数为奇数的字符\(cnt\). \(cnt\ge ...
- Atcoder CODE FESTIVAL 2017 qual B E - Popping Balls 组合计数
题目链接 题意 \(A+B\)个球排成一行,左边\(A\)个为红球,右边\(B\)个为蓝球. 最开始可以选择两个数\(s,t\),每次操作可以取左起第\(1\)或\(s\)或\(t\)个球.问有多少种 ...
随机推荐
- JDK安装与配置环境变量
1.JDK的安装 (1).为什么安装jdk? JDK是java软件开发包的简称,要想开发java程序就必须安装JDK.没有JDK的话,无法编译Java程序. (2).开始安装jdk 1.官网下载jdk ...
- 基于Javaee的影视创作论坛的设计与实现
基于Javaee的影视创作论坛的设计与实现主要用功能包括: 首页推荐.用户管理.影片管理.评论管理. 预告片管理.海报管理.公告管理.数据检索.用户注册与登录等等功能.统结构如下 (1)后台管理: 管 ...
- HDU3746 Cyclic Nacklace
题目链接:https://vjudge.net/problem/HDU-3746 知识点: KMP 解题思路: 论如何用 \(Next[]\) 数组求循环节. AC代码: #include <b ...
- 官网下载Java连接MySql驱动jar包
官网地址:http://dev.mysql.com/downloads/connector/ 1.选择下载驱动 2.选择下载 3.可以不登录直接下载 4.下载下来的是zip压缩包,解压之后,文件夹中有 ...
- Robot Framework(5)- 使用测试库
如果你还想从头学起Robot Framework,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1770899.html 前言 在RF 测 ...
- Spring基础之AOP
一.AOP能解决什么问题 业务层每个service都要管理事务,在每个service中单独写事务,就会产生很多重复性的代码,而且修改事务时,需要修改源码,不利于维护.为此,把横向重复的代码,纵向抽取形 ...
- Docker的iptables规则在iptables重启后丢失
前因后果 1.在跳板机上使用ansible命令测试机器B时,报错如下,于是就怀疑是网络防火墙的问题 10.10.0.86 | FAILED >> { "failed": ...
- 一元三次方程组求解 luogu P1024
题目传送门 首先,要明确题目信息,f(x1) * f(x2) < 0, 则一定存在实数根在区间(x1, x2).且所有的根都在[-100, 100)之间.根与根的绝对值之差 >= 1 那么 ...
- Java中的集合(十一) 实现Map接口的TreeMap
Java中的集合(十一) 实现Map接口的TreeMap 一.TreeMap简介(基于JDK1.8) TreeMap是基于红黑树数据结构,是一个key-value的有序集合,该映射根据其键的自然顺序进 ...
- 解决pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.问题
国内的其他镜像源清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技 ...