【BZOJ 1016】 [JSOI2008]最小生成树计数(matrix-tree定理做法)
来源:互联网 发布:如何学java软件开发 编辑:程序博客网 时间:2024/04/28 09:01
【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1016
【题意】
【题解】
/* 接上一篇文章; 这里用matrix-tree定理搞最小生成树个数; 对于每一种相同边权的边; 当做一个阶段; 这个阶段,我们需要看看这个边权的边能连接哪些联通块; 这里的联通块可以缩为一个点; 这样就相当于在一些点中间插入边; 然后问你这些边能够生成的生成树的个数; 即每个阶段都做一遍matrix-tree定理; martrix-treee定理想要做的话; 你得先得出一张图,最好弄出它的邻接矩阵; 然后可以这样吧。 把这张图缩点之后的节点都标成新的节点; 然后根据新添加进来的边; 建立一张新的图, 然后在这张新图上求生成树; 根据前一篇的分析可知这样的生成树一定是最小生成树的一部分; 建立新图的话也不会难吧; 如果节点之前没出现过就递增节点就好; 然后统计这张新图里面节点的个数; 然后处理出邻接矩阵和度数就能搞了; 不过这样处理会有重边的哦; 当然这个定理也能处理有重边的情况,所以不慌. 每次把生成树的个数根据乘法原则乘到答案上就好 (新的图上可能会有多个连通块,要每个连通块分别算,不然整张图都不是联通的,你再用 整张图去求的话会出错) (初始化什么的一定要认真检查啊); (这个行列式的求法不要用double类,不然精度不够,用int。。不知道为什么可以用int..)*/
推荐一个题解吧
http://www.cnblogs.com/flipped/p/5769228.html
要记住是度数矩阵减去邻接矩阵啊.
【完整代码】
#include <bits/stdc++.h>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define LL long long#define rep1(i,a,b) for (int i = a;i <= b;i++)#define rep2(i,a,b) for (int i = a;i >= b;i--)#define mp make_pair#define pb push_back#define fi first#define se second#define rei(x) scanf("%d",&x)#define rel(x) scanf("%lld",&x)typedef pair<int, int> pii;typedef pair<LL, LL> pll;const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };const double pi = acos(-1.0);const int N = 110;const int M = 1e3 + 100;const int MOD = 31011;struct abc{ int x, y, z;};int n, m,tot,cnt = 0;int f[N],D[N][N],A[N][N],C[N][N],ka[N],g[N][N];int bo[N];abc bian[M];double a[N][N];vector <int> v[N];long long ans = 1;bool cmp1(abc a, abc b){ return a.z < b.z;}int ff(int x){ if (f[x] == x) return x; else return f[x] = ff(f[x]);}int fk(int x){ if (ka[x] == x) return x; else return ka[x] = fk(ka[x]);}int cl(int c[N][N], int n) { int i, j, k, t, ret = 1; for (i = 1; i<=n-1; i++) { for (j = i + 1; j<=n-1; j++) while (c[j][i]) { t = c[i][i] / c[j][i]; for (k = i; k<n; k++) c[i][k] = (c[i][k] - c[j][k] * t) % MOD; swap(c[i], c[j]); ret = -ret; } if (c[i][i] == 0) return 0; ret = ret*c[i][i] % MOD; } return (ret + MOD) % MOD;}int main(){ //freopen("F:\\rush.txt", "r", stdin); rei(n), rei(m); rep1(i, 1, m) rei(bian[i].x), rei(bian[i].y), rei(bian[i].z); sort(bian + 1, bian + 1 + m,cmp1); ans = 1; rep1(i, 1, n) f[i] = i,ka[i] = i; rep1(i, 1, m) { int l = i, r = i; while (r + 1 <= m && bian[r + 1].z == bian[l].z) r++; rep1(j, 1, n) rep1(jj, 1, n) g[j][jj] = 0; rep1(j, 1, n) bo[j] = 0; rep1(j, l, r) { int x = bian[j].x, y = bian[j].y; int r1 = ff(x), r2 = ff(y); if (r1 != r2) { int rr1 = fk(r1), rr2 = fk(r2); if (rr1 != rr2) ka[rr1] = rr2; bo[r1] = true, bo[r2] = true; g[r1][r2]++, g[r2][r1]++; } } rep1(j, 1, n) v[j].clear(); rep1(j, 1, n) if (bo[j]) v[fk(j)].push_back(j); rep1(j,1,n) if (int(v[j].size()) > 1) { rep1(k, 1, n) rep1(kk, 1, n) D[k][kk] = A[k][kk] = 0; int len = v[j].size(); rep1(k,0,len-2) rep1(l, k + 1, len - 1) { int x = v[j][k], y = v[j][l]; if (g[x][y]) { D[k+1][k+1] += g[x][y], D[l+1][l+1] += g[x][y]; A[l+1][k+1] = A[k+1][l+1] = g[x][y]; } } rep1(k, 1,len ) rep1(kk, 1, len) C[k][kk] = D[k][kk] - A[k][kk]; tot = len; ans = (ans*cl(C,len)) % MOD; } rep1(j, l, r) { int x = bian[j].x, y = bian[j].y; int r1 = ff(x), r2 = ff(y); if (r1 != r2) { f[r1] = r2; cnt++; } } rep1(j, 1, n) ka[j] = f[j]; i = r; } if (cnt != n - 1) return puts("0"),0; printf("%lld\n", ans); return 0;}
0 0
- 【BZOJ 1016】 [JSOI2008]最小生成树计数(matrix-tree定理做法)
- BZOJ 1016 [JSOI2008]最小生成树计数 Kruskal Matrix-Tree定理
- [矩阵树定理 模板题] BZOJ 1016 [JSOI2008]最小生成树计数 & HDU 4408 Minimum Spanning Tree
- bzoj 1016: [JSOI2008]最小生成树计数 (矩阵树定理+最小生成树)
- 【BZOJ 1016】 [JSOI2008]最小生成树计数
- BZOJ 1016: [JSOI2008]最小生成树计数
- BZOJ 1016 [JSOI2008]最小生成树计数
- BZOJ 1016 [JSOI2008] 最小生成树计数
- [BZOJ]1016: [JSOI2008]最小生成树计数
- bzoj 1016: [JSOI2008]最小生成树计数
- bzoj 1016: [JSOI2008]最小生成树计数
- bzoj 1016: [JSOI2008]最小生成树计数
- [生成树 MatrixTree定理] BZOJ 1016 [JSOI2008]最小生成树计数
- BZoj 1016: [JSOI2008]最小生成树计数【最小生成树】
- 【BZOJ】1016 生成树计数 最小生成树 Maxtrix-Tree定理 生成树计数 搜索
- 最小生成树计数(Kruskal+Matrix-Tree定理)
- BZOJ 1016 JSOI2008 最小生成树计数 Kruskal
- 【bzoj 1016】[JSOI2008]最小生成树计数 脑残是病
- R 语言文件读写
- 使用swift3创建自己的pod
- [LeedCode]Find the Duplicate Number/Linked List Cycle II
- POJ 2803 Defining Moment 再想想
- 【译】深入学习JavaScript闭包
- 【BZOJ 1016】 [JSOI2008]最小生成树计数(matrix-tree定理做法)
- Sublime Text 全程指引 by Lucida
- 【OpenCV图像处理】八、图像的掩码操作
- 原生session与session in redis对比
- 数学题-leetcode
- 2分钟教你怎样在eclipse上集成maven,,,,
- Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 暴力,二分图,并查集
- web第三节课作业
- Kali Linux安装之后需要做的一些事