【题目链接】: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;
}

【BZOJ 1016】 [JSOI2008]最小生成树计数(matrix-tree定理做法)的更多相关文章

  1. BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)

    题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...

  2. bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...

  3. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  4. [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】

    题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...

  5. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  6. BZOJ 1016 [JSOI2008]最小生成树计数 ——Matrix-Tree定理

    考虑从小往大加边,然后把所有联通块的生成树个数计算出来. 然后把他们缩成一个点,继续添加下一组. 最后乘法原理即可. 写起来很恶心 #include <queue> #include &l ...

  7. bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】

    有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...

  8. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  9. 1016: [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6200  Solved: 2518[Submit][St ...

  10. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

随机推荐

  1. 动态规划例子:Maximal Square

    Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...

  2. 3. Vue-router 路由

    路由是根据不同的url地址展现不同的内容或页面. 前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做(在单页面应用,大部分页面结构不变,只改变部分内容的使用),之前是通过服务器根据url的不 ...

  3. JS里的函数的call()与back()方法

    function cat(){} cat.prototype={ food:"fish", say: function(){ alert("I love "+t ...

  4. 【Codeforces Round #432 (Div. 1) B】Arpa and a list of numbers

    [链接]h在这里写链接 [题意] 定义bad list是一个非空的.最大公约数为1的序列.给定一个序列,有两种操作:花费x将一个元素删除.花费y将一个元素加1,问你将这个序列变为good list所需 ...

  5. php实现 24点游戏算法

    php实现 24点游戏算法 一.总结 一句话总结:把多元运算转化为两元运算,先从四个数中取出两个数进行运算,然后把运算结果和第三个数进行运算,再把结果与第四个数进行运算.在求表达式的过程中,最难处理的 ...

  6. amazeui学习笔记--js插件(UI增强4)--下拉组件Dropdown

    amazeui学习笔记--js插件(UI增强4)--下拉组件Dropdown 一.总结 1.am-dropdown(及其孩子):控制下拉列表的样式 2.data-am-dropdown(及其孩子):控 ...

  7. volatile关键字深入理解

    前言: 这个关键字的重点就三个字,就是可见性.但是面试的时候,你说出可见性三个字,基本上满分100的话,最多只能得到20分.剩下的那80分,就要靠你用硬功夫去获得了. 所谓的硬功夫,其实就是要整明白, ...

  8. disabled的值无法传递到action层

    假设想让表单不可输入的状态,我将表单设置为了: style="cursor:not-allowed;" disabled 可是这样设置之后就发现,在后台的action怎么都没有办法 ...

  9. Visual Studio中你所不知道的智能感知

    在Visual Studio中的智能感知,相信大家都用过.summary,param,returns这几个相信很多人都用过的吧.那么field,value等等这些呢. 首先在Visual Studio ...

  10. 25、写一个USB摄像头驱动程序(有ioctrl分析)

    videobuf2-core.h中的vb2_buffer,记录了v4l2_buffer ,驱动可以对vb2_buffer的v4l2_buffer进行操控, vb2_buffer是v4l2框架层的代码, ...