最小生成树计数

【问题描述】

现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。

【输入格式】

第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。

【输出格式】

输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。

【样例输入】

4 6

1 2 1

1 3 1

1 4 1

2 3 2

2 4 1

3 4 1

【样例输出】

8


题解:

1.用克鲁斯卡尔求一遍最小生成树,统计出某一权值在最小生成树中的个数(即所有权值相同的边的个数)

2.考虑对于每一种权值的方案(Dfs)

要求:

(1)选出的边数等于最小生成树中该权值拥有的边数

原理:最小生成树中每种权值的边数不变

(2)不含环,判断是否有环可以用不压缩路径的并查集处理

原理:树中不含环

3.将所有权值的方案相乘

原理:在最小生成树中对于每一种权值的合法方案构建出的图的连通情况相同

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
inline int Get()
{
int x = , s = ;
char c = getchar();
while('' > c || c > '')
{
if(c == '-') s = -;
c = getchar();
}
while('' <= c && c <= '')
{
x = (x << ) + (x << ) + c - '';
c = getchar();
}
return x * s;
}
struct shape
{
int x, y, z;
};
shape a[];
int n, m, k;
int tot;
int cnt;
int sum;
int l[];
int r[];
int s[];
int fat[];
int c[];
int u[];
inline bool rule(shape a, shape b)
{
return a.z < b.z;
}
int Find(int x)
{
while(fat[x] != x) x = fat[x];
return x;
}
void Dfs(int fig, int va, int le)
{
if(fig == s[va])
{
sum = (sum + ) % ;
if(sum == )
for(int i = ; i <= c[]; ++i)
u[i] = c[i];
// for(int i = 1; i <= c[0]; ++i) printf("%d ", c[i]);
// cout<<endl;
return;
}
for(int i = le; i <= r[va]; ++i)
{
int x = Find(a[i].x);
int y = Find(a[i].y);
int cx = fat[x];
if(x == y) continue;
fat[x] = y;
c[++c[]] = i;
Dfs(fig + , va, i + );
fat[x] = cx;
--c[];
}
}
int main()
{
n = Get(), m = Get();
for(int i = ; i <= m; ++i)
{
a[i].x = Get();
a[i].y = Get();
a[i].z = Get();
}
sort(a + , a + + m, rule);
for(int i = ; i <= n; ++i) fat[i] = i;
for(int i = ; i <= m; ++i)
{
if(a[i].z != a[i - ].z)
{
r[tot] = i - ;
++tot;
l[tot] = i;
}
if(k != n - )
{
int x = Find(a[i].x), y = Find(a[i].y);
if(x != y)
{
fat[x] = y;
++s[tot];
++k;
}
}
}
if(k != n - )
{
printf("");
return ;
}
r[tot] = m;
for(int i = ; i <= n; ++i) fat[i] = i;
int ans = ;
for(int i = ; i <= tot; ++i)
if(s[i])
{
sum = ;
Dfs(, i, l[i]);
for(int l = ; l <= u[]; ++l)
{
int x = Find(a[u[l]].x);
int y = Find(a[u[l]].y);
fat[x] = y;
}
ans = (ans * sum) % ;
}
printf("%d", ans);
}

最小生成树计数 bzoj 1016的更多相关文章

  1. 最小生成树的边的概念问题!!! 最小生成树的计数 bzoj 1016

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

  2. 1016: [JSOI2008]最小生成树计数 - BZOJ

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

  3. 【BZOJ】【1016】【JSOI2008】最小生成树计数

    Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的 ...

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

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

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

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

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

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

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

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

  8. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

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

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

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

随机推荐

  1. js报错: Uncaught RangeError: Invalid string length

    在ajax请求后得到的json数据,遍历的时候chrome控制台报这个错误:Uncaught RangeError: Invalid string length,在stackoverflow查找答案时 ...

  2. Flex 布局教程:实例篇

    该教程整理自 阮一峰Flexible教程 今天介绍常见布局的Flex写法.你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我的主要参考资料是Landon Schropp的文章和Solved ...

  3. 打破陈规抓痛点,H3 BPM10.0挑战不可能

    高效益意味着相似的运营活动比竞争对手做得更好,而战略定位则意味着企业在运营活动中有区别于竞争对手的实施方式,即差异化竞争.在新经济体下,面对社会的变革.市场的竞争环境.不断攀升的成本压力,几乎没有企业 ...

  4. Android之网络数据存储

    一.网络保存数据介绍 可以使用网络来保存数据,在需要的时候从网络上获取数据,进而显示在App中. 用网络保存数据的方法有很多种,对于不同的网络数据采用不同的上传与获取方法. 本文利用LeanCloud ...

  5. BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Stat ...

  6. python之浅拷贝和深拷贝

    1.浅拷贝 1>赋值:从下面的例子我们可以看到赋值之后新变量的内存地址并没有发生任何变化,实际上python中的赋值操作不会开辟新的内存空间,它只是复制了新对象的引用,也就是说除了b这个名字以外 ...

  7. DataTable转换成IList<T>的简单实现

    DataTable的无奈 很多时候,我们需要去操作DataTable.但DataTable的操作,实在是太不方便了.Linq?lambda表达式?统统没有... 特别是对现有结果集做进一步筛选,这样的 ...

  8. RabbitMQ的安装过程

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 网上一些安装教程都较为繁琐,实际上只需要两个RPM包,几分钟即可完成一台实例部署. 准备下载Erlang包: ht ...

  9. ABP框架 - 仓储

    文档目录 本节内容: 默认仓储 自定义仓储 自定义仓储接口 自定义仓储实现 基仓储方法 查询 获取单个实体 获取实体列表 关于 IQueryable 自定义返回值 插入 更新 删除 其它 关于异步方法 ...

  10. Win下必备利器之Cmder

    诚言,对于开发码字者,Mac和Linux果断要比Windows更贴心;但只要折腾下,Windows下也是有不少利器的.之前就有在Windows下效率必备软件一文中对此做了下记载:其虽没oh-my-zs ...