@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\)个球.问有多少种 ...
随机推荐
- 基于 abp vNext 和 .NET Core 开发博客项目 - 再说Swagger,分组、描述、小绿锁
在开始本篇正文之前,解决一个 @疯疯过 指出的错误,再次感谢指正. 步骤如下: 删掉.Domain.Shared层中的项目引用,添加nuget依赖包Volo.Abp.Identity.Domain.S ...
- form提交(图片,excel其他文件)
HTML表单需要设置enctype="multipart/form-data"这个属性,如果不这么设置,在提交表单时候,相关文件将无法获取. HTML表单如何打包数据文件是由enc ...
- SpringBoot踩坑日记
1.Closing JPA EntityManagerFactory for persistence unit 'default'错误导致springboot启动后终止 --------------- ...
- 同一父进程下的子进程之间的通信(pipe通信)
首先对于fork命令 通过fork命令创建进程 父进程返回子进程id 子进程返回0 失败返回-1 对于pipe通讯机制 pipe通讯是半双工的 也就是说只能一方读一方写 题目中想要P1的输出作为 ...
- layui table 数据表格固定列的行高和table其他列的行高不一致
1.问题描述:使用layui的table数据表格,固定某一列,这样表格中数据的宽度超出屏幕宽度时,固定列可以一直显示在屏幕中,不会随着底部滚动栏左右的拖动而变化位置.但是遇到一个问题,就是固定列的行高 ...
- react中路由不起作用的奇怪现象
同样的两段Router代码,为什么一段正常,一段不起作用(也没有任何错误log提示) 瞪着眼观察也看不出为什么... 通过选中高亮显示内容相同, 为何就是有一段路由不管用呢? 折腾半天发现... 大小 ...
- android小Demo--圆球跟随手指轨迹移动
eatwhatApp的客户端基本实现,会再后续进行整改,今天做一个在网上找到的小Demo,让屏幕中出现一个圆球,并跟随手指移动. 写个java类DrawView继承于View: public clas ...
- bootstrap table Showing 1 to 5 of 5 rows 页码显示英文
注意导包先后顺序bootstrap-table-zh-CN.js链接:https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.16.0/locale/b ...
- python九九乘法表程序代码
按照c语言的思路来考虑python的,方法很简单,直接运用双重循环即可,本代码为了代码量少采用的是while嵌套双循环. 取两个随机变量 (1)i和j都从1开始(因为表中最小数值为1) (2)i控制第 ...
- 报错:The server cannot be started because one or more of the ports are invalid. Open the server editor and correct the invalid ports.
今天重装eclipse和Tomcat,启动时候报标题错“The server cannot be started because one or more of the ports are invali ...