矩阵树定理--luoguP4208 [JSOI2008]最小生成树计数
传送门
以前用dfsdfsdfs做的,用基尔霍夫矩阵真的玄啊
首先这道题有这么几个定理:(来自Z-Y-Y-S的博客)
定理一:如果 A,BA, BA,B 同为 GGG 的最小生成树,且 AAA 的边权从小到大为 w(a1),w(a2),w(a3),⋯w(an)w(a_1), w(a_2), w(a_3), \cdots w(a_n)w(a1),w(a2),w(a3),⋯w(an),BBB 的边权从小到大为 w(b1),w(b2),w(b3),⋯w(bn)w(b_1), w(b_2), w(b_3), \cdots w(b_n)w(b1),w(b2),w(b3),⋯w(bn),则有 w(ai)=w(bi)w(a_i) = w(b_i)w(ai)=w(bi)。
证明:设 A,BA, BA,B 第一个不同的边的下标为 iii,不妨设 w(ai)≤w(bi)w(a_i) \le w(b_i)w(ai)≤w(bi),如果不存在这样的 iii,无需证明。
情况一:aia_iai 在 BBB 中,为 bjb_jbj。那么显然有 j>ij>ij>i(否则 iii 不是第一个不同的边),则有 w(ai)≤w(bi)≤w(bj)=w(ai)w(a_i)\le w(b_i) \le w(b_j) = w(a_i)w(ai)≤w(bi)≤w(bj)=w(ai),所以有 w(ai)=w(bi)=w(bj)w(a_i) = w(b_i) = w(b_j)w(ai)=w(bi)=w(bj),所以可以调换 bi,bjb_i, b_jbi,bj 的位置,BBB 的权值排列不会改变, AAA 与 BBB 这样前 iii 条边均为相等,可以递归下去证明。
情况二:aia_iai 不在 BBB 中。考虑将 aia_iai 加入 BBB,则形成了一个环,环中的权值 v≤w(ai)v\le w(a_i)v≤w(ai)(否则 BBB 不是最小生成树),且一定有一条边 bjb_jbj 不在 BBB 中,此时仍有 j>ij>ij>i(否则 iii 不是第一个不同的边),所以有 w(ai)≤w(bi)≤w(bj)≤w(ai)w(a_i)\le w(b_i) \le w(b_j) \le w(a_i)w(ai)≤w(bi)≤w(bj)≤w(ai),所以仍有 w(ai)=w(bi)=w(bj)w(a_i) = w(b_i) = w(b_j)w(ai)=w(bi)=w(bj),可以将 bjb_jbj 替换为 aia_iai,BBB 的权值排列不会改变且仍为最小生成树,仍然调换 bi,bjb_i, b_jbi,bj 的位置,BBB 的权值排列仍会改变,这样 AAA 与 BBB 前 iii 条边均为相等,可以递归下去证明。这样换边不会有问题,因为 Kruskal 算法中唯一的状态就是连通性,我们没有改变其连通性,所以是可以递归证明的。
定理二:如果 A,BA, BA,B 同为 GGG 的最小生成树,如果 A,BA, BA,B 都从零开始从小到大加边(AAA 加 AAA 的边,BBB 加 BBB 的边)的话,每种权值加完后图的联通性相同。
证明:归纳法证明,没有边时显然成立,假设对于权值小于 vvv 的成立。考虑权值为 vvv 的边,如果连通性不相同,必然存在 u,vu, vu,v 两点间连通性不同,假设 AAA 中 u,vu, vu,v 联通,根据 A,BA, BA,B 所有小于 vvv 的边连通性相同,所以必然存在一条 u→vu\rightarrow vu→v 权值为 vvv 的边,而根据 Kruskal 算法的执行过程, BBB 不可能不加这条边,所以两棵最小生成树 A,BA, BA,B 各自权值小于等于 vvv 的边仍然满足连通性相同。由归纳法可知定理二成立。
定理三:如果在最小生成树 AAA 中权值为 vvv 的边有 kkk 条,用任意 kkk 条权值为 vvv 的边替换 AAA 中的权为 vvv 的边且不产生环的方案都是一棵合法最小生成树。
证明:根据之前的定理,其余的边造成的连通性是定的,权值和也是定的,那么选 kkk 条不产生环一定能形成一棵树,而且权值与最小生成树的权值一样,故也是最小生成树。
有了这些定理,就可以基尔霍夫矩阵来算方案,每次乘起来,但算的时候要先“缩点”,其实就是排个序去重之类的,然后算完方案随便找一种连起来,但注意算方案的时候有可能不能构成生成树,还需要先把图再连一下使它能有生成树。
细节很多,写的时候一定要脑子清楚
代码如下:(改动比较多,有点丑)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 105
#define M 1005
#define LL long long
#define int LL
using namespace std;inline int rd(){int x=0,f=1;char c=' ';while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();return x*f;
}int n,m,a[N][N],fa[N],fa2[N],ans=1,c[N<<1],sum;
const int mod=31011;struct EDGE{int fr,to,w;bool operator <(const EDGE &x) const{return w<x.w;}
}edge[M],tmp[M];inline int Matrix_tree(int tot){for(int i=1;i<tot;i++)for(int j=1;j<tot;j++)a[i][j]=(a[i][j]+mod)%mod;int ans=1,f=1;for(int i=1;i<tot;i++){for(int j=i+1;j<tot;j++){if(!a[j][i]) continue;int A=a[i][i],B=a[j][i];while(B){int t=A/B;A%=B; swap(A,B);for(int k=i;k<tot;k++) a[i][k]=(a[i][k]-1LL*t*a[j][k]+mod)%mod;for(int k=i;k<tot;k++) swap(a[i][k],a[j][k]); f=-f;}}if(!a[i][i]) return 0;ans=1LL*ans*a[i][i]%mod;}if(f==-1) ans=mod-ans%mod;return (ans+mod)%mod;
}inline int find(int x){if(x==fa[x]) return x;return fa[x]=find(fa[x]);
}
inline int find2(int x){if(x==fa2[x]) return x;return fa2[x]=find2(fa2[x]);
}inline int solve(int l,int r){int cnt=0,num=0;for(int i=l;i<=r;i++){int x=find(edge[i].fr),y=find(edge[i].to);tmp[i].fr=x,tmp[i].to=y;if(x!=y)c[++num]=x,c[++num]=y;}sort(c+1,c+num+1); num=unique(c+1,c+num+1)-c-1;for(int i=1;i<=num;i++) fa2[i]=i;for(int i=l;i<=r;i++){if(tmp[i].fr==tmp[i].to) continue;int u=find(tmp[i].fr),v=find(tmp[i].to);if(u!=v) sum--,fa[u]=v;u=lower_bound(c+1,c+num+1,tmp[i].fr)-c; v=lower_bound(c+1,c+num+1,tmp[i].to)-c;a[u][u]++,a[u][v]--,a[v][v]++,a[v][u]--;int x=find2(u),y=find2(v);if(x!=y) fa2[x]=y;} for(int i=2;i<=num;i++)if(find2(i)!=find2(i-1)){int u=find2(i),v=find2(i-1);a[u][u]++,a[u][v]--,a[v][v]++,a[v][u]--;fa2[u]=v;}ans=1LL*ans*Matrix_tree(num)%mod;
}signed main(){n=rd(); m=rd();for(int i=1;i<=m;i++) edge[i].fr=rd(),edge[i].to=rd(),edge[i].w=rd();sort(edge+1,edge+m+1); int u,v; sum=n;for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;){int j=i; while(edge[j].w==edge[i].w) j++; j--;if(i==j){u=find(edge[i].fr),v=find(edge[i].to);if(u!=v) fa[u]=v,sum--;}else{memset(a,0,sizeof a); solve(i,j);}i=j+1;}if(sum>1) puts("0");else printf("%lld\n",ans);return 0;
}
矩阵树定理--luoguP4208 [JSOI2008]最小生成树计数相关推荐
- [XSY]Tree Ext(矩阵树定理,拉格朗日插值,最小生成树,二分)
Tree Ext 这道题相当于把3道题合了起来. 要求修复的边中恰好有 k 条白边: 五颜六色的幻想乡(附拉格朗日插值法求多项式系数 ) + bzoj2654 tree(WQS二分 新科技get) 是 ...
- [P4455][CQOI2018]社交网络(矩阵树定理)
关于矩阵树定理用于有向图生成树计数: ①内向树生成树计数. A为邻接矩阵, D为出度矩阵. C=D−A. 以root为根的内向生成树个数为C的余子式M[root,root]的行列式. ②外向树 ...
- BZOJ1016 || 洛谷P4208 [JSOI2008]最小生成树计数【矩阵树定理】
时空限制 1000ms / 128MB 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则 ...
- 最小生成树、矩阵树定理、Prufer序列总结
Kruskal算法 按边权排序,从小到大合并不在同一集合两点即可 Prim算法 每次加入一个到当前已选点集最近的点 P2619 [国家集训队]Tree I 考虑二分,每次给白边加上一个mid,通过这种 ...
- 基尔霍夫(kirchhoff)矩阵树定理
引入问题 给n个点m条边的图,求该图的最小生成树个数. 定理内容 我们对这个图构造两个矩阵,分别是这个图的连通矩阵和度数矩阵.连通矩阵S1S1S1的第iii行第jjj列上的数字表示原无向图中编 ...
- 【学习笔记】矩阵树定理(Matrix-Tree)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 一.矩阵树定理 二.常用定理 三.例题 1. Luogu P6178 [模板]Matrix-Tr ...
- 图论数学:矩阵树定理
运用矩阵树定理进行生成树计数 给定一个n个点m条边的无向图,问生成树有多少种可能 直接套用矩阵树定理计算即可 矩阵树定理的描述如下: 首先读入无向图的邻接矩阵,u-v G[u][v]++ G[v][u ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 6032 Solved: 2452 [Submit][ ...
- CSU 1805 Three Capitals(矩阵树定理+Best定理)
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1805 题意: A和B之间有a条边,A和G之间有b条边,B和G之间有c条边.现在从A点出发走遍所 ...
最新文章
- 7-22 堆栈模拟队列 (25 分)
- java 数据库提交,java.sql.Statement向数据库提交的语句不可以是SQL语句的()。
- Codeforces 698D Limak and Shooting Points (搜索)
- when click one item in table Select at least one column to perform the search
- unsigned char s1 : 2的用法
- 最佳实践|Spring Boot 应用如何快速接入 Prometheus 监控
- 作为一个程序员,CPU的这些硬核知识你必须会!
- C++ 与 php 的交互 之----- C++ 异步获取 网页文字内容,异步获取 php 的 echo 值。...
- PyTorch 1.0 中文官方教程:序列模型和LSTM网络
- seleniuim面试题1
- 一些推荐的深度学习、机器学习资料
- ubuntu 一张网卡绑定多个ip
- phpredis中文手册《redis中文手册》php版
- Neo4j 图数据库高级应用系列 / 服务器扩展指南 APOC 8.6 - 图生成 小世界模型
- idea自动更新IDE Eval Reset插件安装
- poj2069求最小外接球半径 模拟退火
- 罗振宇 知识就是力量之 怎样重新获得别人的信任
- Do it for success
- 如何使用万能地图下载器下载矢量路网
- ReportView报表控件使用方法
热门文章
- 梦想世界3手游服务器维护,梦想世界手游进不去 闪退及登录不上解决方法
- 基于Hadoop豆瓣电影数据分析(综合实验)
- web前端之百度首页仿写
- python halcon_HALCON高级篇:常用分类器及其特点
- anr用户无响应问题的解决
- 【vue-router源码】五、router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes源码分析
- 计算机排版打字操作,五笔字型与计算机排版培训教程2版 第9章 打字与排版的首选—Word 2007.ppt...
- Chrome浏览器支持的时间格式
- 基于Docker搭建DzzOffice与OnlyOffice线上协同办公服务器
- 协议和服务器有什么区别,服务期协议是什么,劳动合同与服务期协议有什么区别?...