题目描述

给出一张无向图,求满足 0号点到所有点的路径长等于原图中它们之间最短路 的生成树的个数。

输入

第一行一个整数N,代表原图结点。
接下来N行,每行N个字符,描绘了一个邻接矩阵。邻接矩阵中,
如果某一个元素为0,代表这两个点之间不存在边,
并且保证第i行第i列的元素为0,第i行第j列的元素(i≠j)等于第j行第i列的元素。
2≤N≤50

输出

一行一个整数,代表删法总方案数膜1,000,000,007的结果。

样例输入

4
0123
1012
2101
3210

样例输出

6


题解

最短路+矩阵树定理

首先求出这张图以0为起点的最短路径图,即边只能在这些图中选择。这里由于数据范围小,随便哪种最短路都可以。代码中写了Floyd。

然后考虑一个点是从哪个个节点更新的:最短路径图上指向它的所有边都可以选择。(注意:最短路径图是有向的。即如果a能更新b则有a->b,不代表b能更新a。)

所以答案就是最短路径图上以0为根的生成外向树形图的数目。求 入度矩阵-邻接矩阵 删去0所在行列的行列式的值即为答案。

时间复杂度$O(n^3)$

UPD:我SB了。。。能直接求出的干嘛要用矩阵树定理。。。

由于最短路径图是一个DAG,因此相当于除了1号点以外,其它点选择其入边的任意一条均可(类似于归纳法),所以答案就是最短路径图中除了一号点以外其它所有的点的入度之积。

(转化为矩阵树定理,即如果按照拓扑序给点编号的话,相当于得到的矩阵是一个上三角矩阵,直接求对角线(入度)乘积即为答案)。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define N 50
  5. #define mod 1000000007
  6. using namespace std;
  7. typedef long long ll;
  8. int map[N][N] , dis[N][N];
  9. ll a[N][N];
  10. char str[60];
  11. inline ll pow(ll x , int y)
  12. {
  13. ll ans = 1;
  14. while(y)
  15. {
  16. if(y & 1) ans = ans * x % mod;
  17. x = x * x % mod , y >>= 1;
  18. }
  19. return ans;
  20. }
  21. int main()
  22. {
  23. int n , i , j , k , d = 0;
  24. ll t , ans = 1;
  25. scanf("%d" , &n);
  26. memset(map , 0x3f , sizeof(map)) , memset(dis , 0x3f , sizeof(dis));
  27. for(i = 0 ; i < n ; i ++ )
  28. {
  29. scanf("%s" , str) , dis[i][i] = 0;
  30. for(j = 0 ; j < n ; j ++ )
  31. if(str[j] != '0')
  32. map[i][j] = dis[i][j] = str[j] - '0';
  33. }
  34. for(k = 0 ; k < n ; k ++ )
  35. for(i = 0 ; i < n ; i ++ )
  36. for(j = 0 ; j < n ; j ++ )
  37. dis[i][j] = min(dis[i][j] , dis[i][k] + dis[k][j]);
  38. for(i = 0 ; i < n ; i ++ )
  39. for(j = 0 ; j < n ; j ++ )
  40. if(map[i][j] != 0x3f3f3f3f && dis[0][i] + map[i][j] == dis[0][j])
  41. a[j][j] ++ , a[i][j] = (a[i][j] - 1 + mod) % mod;
  42. for(i = 1 ; i < n ; i ++ )
  43. {
  44. for(j = i ; j < n ; j ++ )
  45. if(a[i][j])
  46. break;
  47. if(j == n) continue;
  48. if(j != i)
  49. {
  50. d ^= 1;
  51. for(k = i ; k < n ; k ++ ) swap(a[i][k] , a[j][k]);
  52. }
  53. ans = ans * a[i][i] % mod;
  54. for(t = pow(a[i][i] , mod - 2) , j = i ; j < n ; j ++ )
  55. a[i][j] = a[i][j] * t % mod;
  56. for(j = i + 1 ; j < n ; j ++ )
  57. for(t = a[j][i] , k = i ; k < n ; k ++ )
  58. a[j][k] = (a[j][k] - a[i][k] * t % mod + mod) % mod;
  59. }
  60. for(i = 1 ; i < n ; i ++ ) ans = ans * a[i][i] % mod;
  61. if(d) ans = (mod - ans) % mod;
  62. printf("%lld\n" , ans);
  63. return 0;
  64. }

【bzoj5056】OI游戏 最短路+矩阵树定理的更多相关文章

  1. BZOJ5056 OI游戏 最短路+组合数学

    链接接接接接! 正解:最短路+小学奥数 乘法原理 解题报告: 首先读懂题意(,,,我觉得我吃枣死于语文太差读不懂题目QAQ 大意就是港,要求从第一个点到其他各点的长度都是最短的方案有多少个(ummm, ...

  2. 【BZOJ4894】天赋(矩阵树定理)

    [BZOJ4894]天赋(矩阵树定理) 题面 BZOJ Description 小明有许多潜在的天赋,他希望学习这些天赋来变得更强.正如许多游戏中一样,小明也有n种潜在的天赋,但有 一些天赋必须是要有 ...

  3. 【bzoj4894】天赋 矩阵树定理

    题目描述 小明有许多潜在的天赋,他希望学习这些天赋来变得更强.正如许多游戏中一样,小明也有n种潜在的天赋,但有一些天赋必须是要有前置天赋才能够学习得到的.也就是说,有一些天赋必须是要在学习了另一个天赋 ...

  4. LOJ #6044 -「雅礼集训 2017 Day8」共(矩阵树定理+手推行列式)

    题面传送门 一道代码让你觉得它是道给初学者做的题,然鹅我竟没想到? 首先考虑做一步转化,我们考虑将整棵树按深度奇偶性转化为一张二分图,即将深度为奇数的点视作二分图的左部,深度为偶数的点视作二分图的右部 ...

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

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

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

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

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

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

  8. 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

    [LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...

  9. 2019.01.02 bzoj2467: [中山市选2010]生成树(矩阵树定理)

    传送门 矩阵树定理模板题. 题意简述:自己看题面吧太简单懒得写了 直接构建出这4n4n4n个点然后按照题面连边之后跑矩阵树即可. 代码: #include<bits/stdc++.h> # ...

随机推荐

  1. python的**和*

    1.**两个乘号就是乘方,比如2**4,结果就是2的4次方,结果是16一个乘号*,如果操作数是两个数字,就是这两个数字相乘,如2*4,结果为8*如果是字符串.列表.元组与一个整数N相乘,返回一个其所有 ...

  2. c/c++面试指导---c语言基础算法总结1

    c语言基础算法总结 1  初学者学习任何一门编程语言都必须要明确,重点是学习编程方法和编程思路,不是学习语法规则,语法规则是为编程实现提供服务和支持.所以只要认真的掌握了c语言编程方法,在学习其它的语 ...

  3. idea中使用逆向工程----三部曲

    逆向工程小伙伴可能都知道,可以根据公司大佬的数据库简单创建实体类和dao接口以及mapper的映射文件,逆向工程可能在数据库字段比较少的时候体现不会方便,但是当参与到数据库字段比较多的时候,我们不可能 ...

  4. php 多维数组相同键值处理合并

    一.前言 在实际情况中,有时需要针对多维数组相同键值作相应的处理(四则运算.比较大小等)后才能够使用到实际情况中,现给出三维数组(多维数组可相应拓展)任意多个相同键值处理的函数,以备查阅. 二.代码 ...

  5. 微信小程序禁止下拉_解决小程序下拉出现空白的情况

    微信小程序禁止下拉 在微信小程序中,用力往下拉动,页面顶部会出现一段空白的地方. 产品的需求不太允许这么做,会影响用户体验,查看文档发现可以使用enablePullDownRefresh这属性来实现, ...

  6. [BZOJ3172 ][Tjoi2013]单词(AC自动机)

    Description 不稳定的传送门 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次.单词个数<=200,单词总长度< ...

  7. 进入saftmode解决方案

    Name node is in safe mode.The reported blocks 356 needs additional 2 blocks to reach the threshold 0 ...

  8. mac上MySQLdb问题解决

    早上有个同学问题python访问mysql的问题,之前的写得脚步突然不能运行了,找了很多文章总算解决问题了O(∩_∩)O哈哈~,希望下次不要浪费这么多时间搞这么坑的问题了.   mac上MySQLdb ...

  9. python面向对象三大特性

    面向对象的三大特性: 封装.继承和多态 一.封装 封装,顾名思义就是将内容封装到某个地方,以后可以直接调用被封装到某处的内容. - 将内容封装到某处 - 从某处调用被封装的内容 第一步,将内容封装到某 ...

  10. 19,django组件之contenttype(一)

    django组件之contenttype(一) 方式1:适用于1张表和另一张表要关联的时候. 1.路飞学成表设计: 2.将2个价格策略表合并1张表. 3.如果再加一张表,那价格策略表的表结构会发生改变 ...