题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=4596

题解:

容斥,矩阵树定理,矩阵行列式

先说说容斥:(一共有 N-1个公司)
令 f[i] 表示选出 (N-1)-i 个公司来修路(即有i个公司一定不修),且不管每个公司只能修一条路这一限制的方案数。
那么 答案 ANS=0个公司不修的方案数 - 1个公司不修的方案数 +2个公司不修的翻案数 ...
即 ANS= f[0] - f[1] +f[2] - ... + (-1)i*f[i]
f[i]的求法呢,就是先O(2N)枚举公司集合情况,
然后用矩阵树定理 O(N3) 求出当前情况下的生成树方案数。
另外再本题中,在构造上三角矩阵用以求行列式时,
既要避免小数,还要不影响原矩阵的行列式的值,
所以采用辗转相除的高斯消元法去构造上三角矩阵。复杂度多一个(logN)
由矩阵行列式的性质可知,这样辗转相除的高斯消元法不会影响行列式的绝对值,
只会影响符号位的正负,所以统计一下正负号的变化就好了。
(还不会矩阵树定理,看看这里,入门一波。)
所以总的时间复杂度为 O(2N*N3*logN)。
(都是这个复杂度,不晓得为什么我的代码跑到这么慢,都垫底了......)

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #define add(x,y) (((1ll*(x)+(y))%mod+mod)%mod)
  5. #define mul(x,y) (((1ll*(x)*(y))%mod+mod)%mod)
  6. #define filein(x) freopen(#x".in","r",stdin)
  7. #define fileout(x) freopen(#x".out","w",stdout)
  8. using namespace std;
  9. const int mod=1000000007;
  10. struct Matrix{
  11. int Val[20][20],*X[20],R,C;
  12. void Init(int r,int c){//r==c
  13. R=r; C=c;
  14. memset(Val,0,sizeof(Val));
  15. for(int i=1;i<=R;i++) X[i]=Val[i];
  16. }
  17. void Modify(int r,int c,int v){
  18. X[r][c]=add(X[r][c],v);
  19. }
  20. void operator =(const Matrix &rtm){
  21. Init(rtm.R,rtm.C);
  22. for(int i=1;i<=R;i++)
  23. for(int j=1;j<=C;j++)
  24. Val[i][j]=rtm.X[i][j];
  25. }
  26. Matrix operator -(const Matrix & rtm) const{
  27. Matrix now; now=*this;
  28. for(int i=1;i<=R;i++)
  29. for(int j=1;j<=C;j++)
  30. now.X[i][j]=add(now.X[i][j],-rtm.X[i][j]);
  31. return now;
  32. }
  33. void Gauss_Euclidean(int p,int &ti){//形成上三角矩阵
  34. if(p==R-1) return;
  35. if(!X[p][p])
  36. for(int i=p+1;i<R;i++) if(X[i][p]){
  37. swap(X[i],X[p]); ti++; break;
  38. }
  39. if(!X[p][p]) return;
  40. for(int i=p+1;i<R;i++){
  41. while(X[i][p]){
  42. int t=X[p][p]/X[i][p];
  43. for(int j=p;j<R;j++)
  44. X[p][j]=add(X[p][j],-mul(X[i][j],t));
  45. swap(X[p],X[i]); ti++;
  46. }
  47. }
  48. Gauss_Euclidean(p+1,ti);
  49. }
  50. int Determinant(){
  51. int ti=0,ans=1;
  52. Gauss_Euclidean(1,ti);
  53. for(int i=1;i<R;i++) ans=mul(ans,X[i][i]);
  54. if(ti&1) ans=mul(ans,-1);
  55. return ans;
  56. }
  57. void print(){
  58. for(int i=1;(i!=1?printf("\n"):0),i<=R;i++)
  59. for(int j=1;j<=R;j++)
  60. printf("%d ",X[i][j]);
  61. }
  62. }A,B,K;
  63. int cpy[20][500];
  64. int ANS,N,tmp;
  65. void dfs(int p,int num){
  66. if(p>=N) return;
  67. //选
  68. for(int i=1,a,b;i<=2*cpy[p][0];i+=2){
  69. a=cpy[p][i]; b=cpy[p][i+1];
  70. A.Modify(a,a,1); A.Modify(b,b,1);
  71. B.Modify(a,b,1); B.Modify(b,a,1);
  72. }
  73. K=A-B; tmp=K.Determinant();
  74. if(((N-1)-(num+1))&1) tmp=mul(tmp,-1);
  75. ANS=add(ANS,tmp);
  76. dfs(p+1,num+1);
  77. //不选
  78. for(int i=1,a,b;i<=2*cpy[p][0];i+=2){
  79. a=cpy[p][i]; b=cpy[p][i+1];
  80. A.Modify(a,a,-1); A.Modify(b,b,-1);
  81. B.Modify(a,b,-1); B.Modify(b,a,-1);
  82. }
  83. dfs(p+1,num);
  84. }
  85. int main()
  86. {
  87. scanf("%d",&N);
  88. A.Init(N,N); B.Init(N,N);
  89. for(int i=1;i<=N-1;i++){
  90. scanf("%d",&cpy[i][0]);
  91. for(int j=1;j<=2*cpy[i][0];j++)
  92. scanf("%d",&cpy[i][j]);
  93. }
  94. dfs(1,0);
  95. printf("%d",ANS);
  96. return 0;
  97. }

●BZOJ 4596 [Shoi2016]黑暗前的幻想乡的更多相关文章

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

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

  2. BZOJ 4596: [Shoi2016]黑暗前的幻想乡

    Sol 容斥原理+Matrix-Tree定理.容斥跟小星星那道题是一样的,然后...直接Matrix-Tree定理就可以了... 复杂度\(O(2^{n-1}n^3)\) PS:调了好久啊QAQ 明明 ...

  3. bzoj 4596: [Shoi2016]黑暗前的幻想乡【容斥原理+矩阵树定理】

    真是简单粗暴 把矩阵树定理的运算当成黑箱好了反正我不会 这样我们就可以在O(n^3)的时间内算出一个无向图的生成树个数了 然后题目要求每个工程队选一条路,这里可以考虑容斥原理:全选的方案数-不选工程队 ...

  4. BZOJ 4596: [Shoi2016]黑暗前的幻想乡(容斥+Matrix_Tree)

    传送门 解题思路 看到计数想容斥--\(from\) \(shadowice1984\)大爷.首先求出原图的生成树个数比较容易,直接上矩阵树定理,但这样会多算一点东西,会把\(n-2\)个公司的多算进 ...

  5. 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 324  Solved: 187 Description ...

  6. 【BZOJ】4596: [Shoi2016]黑暗前的幻想乡

    [题意]给定n个点的无向完全图,有n-1个公司各自分管一部分路,要求所有公司都有修路的生成树数.n<=17. [算法]容斥原理+生成树计数(矩阵树定理) [题解]每个生成树方案是一个公司有无修路 ...

  7. bzoj4596[Shoi2016]黑暗前的幻想乡 Matrix定理+容斥原理

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

  8. bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥)

    bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥) bzoj Luogu 题解时间 看一看数据范围,求生成树个数毫无疑问直接上矩阵树定理. 但是要求每条边都 ...

  9. [ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)

    这两道题思路比较像,所以把他们放到一块. [ZJOI2016]小星星 题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星. ...

随机推荐

  1. HDFS之RPC机制

  2. 学号:201621123032 《Java程序设计》第6周学习总结

    1:本周学习总结 1.1: 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结 2:书面作业 2.1: clone方法 2.1.1 ...

  3. The sum of numbers form 0 to n.(20.9.2017)

    #include <stdio.h> int main() { int a,b,sum; printf("输入一个数字: "); scanf("%d" ...

  4. Django 基本设置

    建立django目录,为了独立区分app和主站的关系,需要把app完全和主站分离 app/views.py from django.shortcuts import render from djang ...

  5. 前端面试题之css

    1.请列出几个具有继承特性的css属性 font-family  font-size  color  line-height  text-align  text-indent 2.阐述display: ...

  6. JAVA_SE基础——61.字符串入门

    public class Demo1 { public static void main(String[] args) { String str1 = "hello"; Strin ...

  7. nodeJS基于smtp发邮件

    邮件的协议smtp是tcp/ip族中的一个协议,所以我们这次考虑使用net模块来发送邮件. const net = require('net') const assert = require('ass ...

  8. python 内置函数之lambda-filter-reduce-apply-map

    (1)lambda lambda是Python中一个很有用的语法,它允许你快速定义单行最小函数.类似于C语言中的宏,可以用在任何需要函数的地方. 基本语法如下: 函数名 = lambda args1, ...

  9. R语言-离职率分析

    案例:员工流失是困扰企业的关键因素之一,在这次的分析中我将分析以下内容: 对一些重要变量进行可视化及探索分析,收入,晋升,满意度,绩效,是否加班等方面进行单变量分析 分析员工流失的因素,探索各个变量的 ...

  10. 新概念英语(1-123)A trip to Australia

    Who is the man with the beard?(胡须)A:Look, Scott. This is a photograph I took during my trip to Austr ...