题意

给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\)

\(n\leq 100\)

分析

  • 考虑矩阵树定理,把对应的树边的边权设置成 \(x\) 然后构造基尔霍夫矩阵, 结果记为 \(val\) ,有

    \[val=\sum_\limits{i=0}^{n-1}x^ians_i
    \]

    其中 \(ans_i\) 表示和 \(S\) 的公共边数量为 \(i\) 的生成树的个数。

  • 发现这是一个关于 \(x\) 的多项式,我们要求每一项的系数 \(ans_i\) ,所以搞出 \(x\in[0, n -1]\) 的 \(val\) 然后高斯消元即可。

  • 总时间复杂度为 \(O(n^4)\)。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
  5. #define rep(i, a, b) for(int i = a; i <= b; ++i)
  6. #define pb push_back
  7. inline int gi() {
  8. int x = 0,f = 1;
  9. char ch = getchar();
  10. while(!isdigit(ch)) {
  11. if(ch == '-') f = -1;
  12. ch = getchar();
  13. }
  14. while(isdigit(ch)) {
  15. x = (x << 3) + (x << 1) + ch - 48;
  16. ch = getchar();
  17. }
  18. return x * f;
  19. }
  20. template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
  21. template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
  22. const int N = 104, mod = 1e9 + 7;
  23. int n;
  24. LL a[N][N], G[N][N], gg[N][N];
  25. LL Pow(LL a, LL b) {
  26. LL res = 1ll;
  27. for(; b; b >>= 1, a = a * a % mod) if(b & 1) res = res * a % mod;
  28. return res;
  29. }
  30. void Gauss(int n, int m, LL (*G)[N]) {
  31. for(int u =0, col = 0; col <= m; ++col, ++u) {
  32. int sel = u;
  33. for(;sel <= n && !G[sel][col]; ++sel);
  34. if(sel > n) { --u; continue;}
  35. if(sel ^ u) {for(int i = 1; i <= m + 1; ++i) swap(G[u][i], G[sel][i]);}
  36. LL inv = Pow(G[u][col], mod - 2);
  37. for(int i = col; i <= m + 1; ++i) G[u][i] = G[u][i] * inv % mod;
  38. for(int v = 1; v <=n; ++v)if(u ^ v) {
  39. LL x = G[v][col];
  40. for(int i = col; i <= m + 1; ++i) G[v][i] = ((G[v][i] - G[u][i] * x) % mod + mod) % mod;
  41. }
  42. }
  43. }
  44. LL det(int n, int m, LL (*G)[N]) {
  45. LL c = 0;
  46. for(int u = 2, col = 2; col <= m; ++col, ++u) {
  47. int sel = u;
  48. for(;sel <= n && !G[sel][col]; ++sel);
  49. if(sel > n) { u--; continue;}
  50. if(sel ^ u) {c ^= 1; for(int i = 1; i <= m; ++i) swap(G[u][i], G[sel][i]);}
  51. for(int v = u + 1; v <= n; ++v)
  52. while(G[v][col]) {
  53. LL x = G[v][col] / G[u][col];
  54. for(int i = col; i <= m; ++i) G[v][i] = ((G[v][i] - x * G[u][i])%mod + mod) % mod;
  55. if(!G[v][col]) break;
  56. c ^= 1;
  57. for(int i = 1; i <= m; ++i) swap(G[u][i], G[v][i]);
  58. }
  59. }
  60. LL ans = 1ll;
  61. for(int i = 2; i <= n; ++i) ans = ans * G[i][i] % mod;
  62. if(c) ans = mod - ans;
  63. return ans;
  64. }
  65. int main() {
  66. n = gi();
  67. rep(i, 1, n - 1){
  68. int u = gi(), v = gi();
  69. a[u][v] ++, a[v][u] ++;
  70. }
  71. rep(x, 0, n - 1) {
  72. memset(G, 0, sizeof G);
  73. rep(i, 1, n)
  74. rep(j, 1, n) {
  75. G[j][j] += (a[i][j] ? x : 1);
  76. G[i][j] -= (a[i][j] ? x : 1);
  77. }
  78. rep(i, 1, n)
  79. rep(j, 1, n) if(G[i][j] < 0) G[i][j] += mod;
  80. gg[x][n] = det(n, n, G);
  81. LL tmp = 1;
  82. for(int i = 0; i < n; ++i, tmp = tmp * x % mod) gg[x][i] = tmp;
  83. }
  84. Gauss(n - 1, n - 1, gg);
  85. for(int i = 0; i < n; ++i) printf("%lld%c", gg[i][n], i == n?'\n':' ');
  86. return 0;
  87. }

[CF917D]Stranger Trees[矩阵树定理+解线性方程组]的更多相关文章

  1. CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)

    题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...

  2. Codeforces 917D - Stranger Trees(矩阵树定理/推式子+组合意义)

    Codeforces 题目传送门 & 洛谷题目传送门 刚好看到 wjz 在做这题,心想这题之前好像省选前做过,当时觉得是道挺不错的题,为啥没写题解呢?于是就过来补了,由此可见我真是个大鸽子(( ...

  3. CF917D Stranger Trees

    CF917D Stranger Trees 题目描述 给定一个树,对于每个\(k=0,1\cdots n-1\),问有多少个生成树与给定树有\(k\)条边重合. 矩阵树定理+高斯消元 我们答案为\(f ...

  4. 【Learning】矩阵树定理 Matrix-Tree

    矩阵树定理 Matrix Tree ​ 矩阵树定理主要用于图的生成树计数. 看到给出图求生成树的这类问题就大概要往这方面想了. 算法会根据图构造出一个特殊的基尔霍夫矩阵\(A\),接着根据矩阵树定理, ...

  5. 4.9 省选模拟赛 生成树求和 变元矩阵树定理 生成函数 iDFT 插值法

    有同学在loj上找到了加强版 所以这道题是可以交的.LINK:生成树求和 加强版 对于30分 爆搜 可实际上我爆搜只过了25分 有同学使用按秩合并并茶几的及时剪枝通过了30分. const int M ...

  6. UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)

    题面传送门 一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% vfk yyds u1s1 这种题目我是根本想不出来/kk,大概也就 jgh 这样的随机化带师才能想到出来吧 首先看到生成树 ...

  7. [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  8. BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]

    传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...

  9. bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 325[Submit][Sta ...

随机推荐

  1. 查询es curl命令记录

    curl  -H "Content-Type: application/json" -XGET http://10.65.0.33:9200/online/senseLog/_se ...

  2. 【python】字典/dictionary操作

    字典(dictionary) 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值 key=>value 对用冒号:分割,每个键值对之间用逗号,分割,整个字典包括在花括号 {} 中 ...

  3. SQLSERVER中的LOB页面简单研究

    SQLSERVER中的LOB页面简单研究 这篇文章和我另一篇文章是相辅相成的,在看<SQLSERVER2012 列存储索引的简单研究和测试>这篇文章之前希望大家先看一下这篇文章o(∩_∩) ...

  4. SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行

    我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...

  5. python被游标坑了

    为了方便,这次就不单独写脚本了,直接一步一步执行下来就好了先说下游标,就是一个指针,比如我有1234每条占一行,那么初始游标默认是在1的位置,当read(1)后,游标自动向下next,现在指在2的位置 ...

  6. MySQL基础之 AND和OR运算符

    AND和OR运算符 作用:用于基于一个以上的条件对记录进行过滤 用法:可在WHERE子句中把两个或多个条件结合在一起. AND:如果第一个条件和第二个条件都成立,才会显示一条记录 OR:如果第一个条件 ...

  7. vlanif和vlan路由

    配置基于接口划分VLAN示例(接入层设备作为网关) 简介 划分VLAN的方式有:基于接口.基于MAC地址.基于IP子网.基于协议.基于策略(MAC地址.IP地址.接口).其中基于接口划分VLAN,是最 ...

  8. Java BAT大型公司面试必考技能视频-1.HashMap源码分析与实现

    视频通过以下四个方面介绍了HASHMAP的内容 一. 什么是HashMap Hash散列将一个任意的长度通过某种算法(Hash函数算法)转换成一个固定的值. MAP:地图 x,y 存储 总结:通过HA ...

  9. windows下的MySql实现读写分离

    MySql读写分离 1.删除系统服务 sc delete 服务名 2.复制安装好的3380文件夹到3381 3.进入3381\logs目录下将所有文件删除 4.进入3381\data目录,将所有的lo ...

  10. es5与es6继承思考

    es5与es6继承思考 es6继承 class Father{ constructor(name){ this.name = name; } getName(){ console.log(this.n ...