【JSOI 2008】 最小生成树计数
【题目链接】
【算法】
笔者做这题参考了这篇博客 :
https://blog.sengxian.com/solutions/bzoj-1016
推荐阅读
首先,我们需要知道三个定理 :
定理1 : 若A,B是两棵不同的最小生成树,它们的权值从小到大排列分别为 :
W(a1),W(a2),W(a3)....W(an-1)
W(b1),W(b2),W(b3)....W(bn-1)
那么,对于任意的i,都有W(ai) = W(bi)
定理2 : 当最小生成树中所有w <= w0的边被加入后,图的联通性唯一
定理3 : 若A是一棵最小生成树,A中权值为v的边有k条,那么,用任意k条权值为v的边替换A中权值为v的边且不产生
环的方案都是一棵最小生成树
证明详见笔者推荐的那篇博客
有了这三个定理,这题就很好做啦! 首先,任意求一棵最小生成树,记录每种权值的边出现的次数,然后,对每种
权值的边做一遍深度优先搜索DFS,求出方案数,然后乘法原理,即可
【代码】
注意因为进行DFS时需要回溯,所以,并查集不能路径压缩
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
#define MAXM 1010
const int MOD = ; int n,m,i,j,ans = ,pos,len,sum,sx,sy;
int fa[MAXN],s[MAXN],val[MAXN],l[MAXN],r[MAXN]; struct Edge
{
int u,v,w;
} e[MAXM];
inline void init(int n)
{
int i;
for (i = ; i <= n; i++) fa[i] = i;
}
int get_root(int x)
{
if (fa[x] == x) return x;
return get_root(fa[x]);
} bool cmp(Edge a,Edge b)
{
return a.w < b.w;
}
bool kruskal()
{
int i,cnt = ,sx,sy;
for (i = ; i <= m; i++)
{
sx = get_root(e[i].u);
sy = get_root(e[i].v);
if (e[i].w == val[len]) r[len]++;
if (sx != sy)
{
fa[sx] = sy;
cnt++;
if (e[i].w == val[len]) s[len]++;
else
{
len++;
l[len] = r[len] = i;
s[len]++;
val[len] = e[i].w;
}
}
}
return cnt == n - ;
}
inline void dfs(int now,int r,int c)
{
int sx,sy;
if (now > r)
{
if (c == s[pos]) sum++;
return;
}
dfs(now+,r,c);
sx = get_root(e[now].u);
sy = get_root(e[now].v);
if (sx != sy)
{
fa[sx] = sy;
dfs(now+,r,c+);
fa[sx] = sx;
}
} int main() { scanf("%d%d",&n,&m);
for (i = ; i <= m; i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+,e+m+,cmp);
init(n);
if (!kruskal())
{
puts("");
return ;
}
init(n);
for (i = ; i <= len; i++)
{
sum = ;
pos = i;
dfs(l[i],r[i],);
ans = (ans * sum) % MOD;
for (j = l[i]; j <= r[i]; j++)
{
sx = get_root(e[j].u);
sy = get_root(e[j].v);
if (sx != sy) fa[sx] = sy;
}
}
printf("%d\n",ans); return ; }
【JSOI 2008】 最小生成树计数的更多相关文章
- JSOI 2008 最小生成树计数
JSOI 2008 最小生成树计数 今天的题目终于良心一点辣 一个套路+模版题. 考虑昨天讲的那几个结论,我们有当我们只保留最小生成树中权值不超过 $ k $ 的边的时候形成的联通块是一定的. 我们可 ...
- BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索
题目大意:给出一些边,求出一共能形成多少个最小生成树. 思路:最小生成树有非常多定理啊,我也不是非常明确.这里仅仅简单讲讲做法.关于定各种定理请看这里:http://blog.csdn.net/wyf ...
- 最小生成树计数 bzoj 1016
最小生成树计数 (1s 128M) award [问题描述] 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一 ...
- 【bzoj1016】 JSOI2008—最小生成树计数
http://www.lydsy.com/JudgeOnline/problem.php?id=1016 (题目链接) 题意 求图的最小生成树计数. Solution %了下题解,发现要写矩阵树,15 ...
- [BZOJ]1016 JSOI2008 最小生成树计数
最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3517 Solved: 1396[Submit][St ...
- 【BZOJ】【1016】【JSOI2008】最小生成树计数
Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的 ...
- 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集
最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...
- BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1016 给出一张图,其中具有相同权值的边的数目不超过10,求最小生成树的个数. 分析 生成树的计 ...
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
随机推荐
- [Python3网络爬虫开发实战] 1.5.4-RedisDump的安装
RedisDump是一个用于Redis数据导入/导出的工具,是基于Ruby实现的,所以要安装RedisDump,需要先安装Ruby. 1. 相关链接 GitHub:https://github.com ...
- js 技巧 (一)
· 事件源对象 event.srcElement.tagName event.srcElement.type · 捕获释放event.srcElement.setCapture(); event ...
- 微信sdk 签名
<?php namespace app\wechat\service; use think\Config; class Signature { protected $appId ; protec ...
- 51NOD 2368 珂朵莉的旅行
>>这是原题传送门<< 答案参考来自 http://www.cnblogs.com/sugewud/p/9822933.html 思路:思维题OR规律题?个人没写出来,脑子里只 ...
- Borrowers
Description I mean your borrowers of books - those mutilators of collections, spoilers of the symmet ...
- Python操作Redis、Memcache
今天主要介绍如何通过python来对Redis和memcache进行操作,下面开始今天的内容: 一.Memcached操作 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web ...
- IntelliJ IDEA配置本地Tomcat方法---亲测有效
https://blog.csdn.net/hello_ljl/article/details/79258165
- 【扫描线】HDU 5124 lines
http://acm.hdu.edu.cn/showproblem.php?pid=5124 [题意] 在数轴x上,每次操作都覆盖一个区间的所有点,问被覆盖次数最多的点是覆盖了多少次 [思路] 最简单 ...
- SPOJ 3267 D-query (可持久化线段树,区间重复元素个数)
D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair ...
- SPOJ-BRCKTS (括号序列,线段树)
维护括号序列 Replace(i): 将第i个位置的括号反向. Check:测试当前序列是否合法. 题解 将左括号定为1,右括号定为-1,所以只需要满足前缀和序列没有负数即可,即最小值 为正即可,第i ...