BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1016
给出一张图,其中具有相同权值的边的数目不超过10,求最小生成树的个数.
分析
生成树的计数有一个什么什么算法...
我真的企图研究了...但是智商捉急的我实在看不懂论文...
所以最后还是写了暴力...
当然暴力也要靠正确的姿势的.
首先来看一个结论:
同一张图的所有最小生成树中,边权值相同的边的数目是一定的.
也就是说,假如某一张图的某一棵最小生成树由边权值为1,1,2,2,2,3的边组成,那么这张图的所有其他最小生成树也都由六条权值分别为1,1,2,2,2,3的边组成.
至于证明,我们可以用数学归纳法.
1.以上结论对与n=2的情况显然成立.
2.假设对于n=k的情况以上结论成立即k个节点的最小生成树满足相同权值的边的数目一定.那么对于n=k+1的情况,需要加一条边将第k+1个点连起来,因为生成树是最小的,所以所加的边的权值是一定的,而之前的k-1条边(连接之前的k个点的边)各权值的边的数目也是一定的,所以最终各权值的边的数目是一定的.
有了这样的一个结论,又因为相同权值的边的数目不超过10,所以我们就可以利用暴力dfs+乘法原理,统计每一种权值的边的选择的方案数,然后相乘即可.
#include <bits/stdc++.h>
using namespace std; const int maxn=+,maxm=+,mod=;
struct edge{
int u,v,w;
edge(){}
edge(int u,int v,int w):u(u),v(v),w(w){}
bool operator < (const edge &a) const { return w<a.w; }
}g[maxm];
int n,m,cnt,sum,ans=;
int a[maxm],b[maxm],ect[maxm],f[maxn];
inline int read(int &x){x=;int k=;char c;for(c=getchar();c<''||c>'';c=getchar())if(c=='-')k=-;for(;c>=''&&c<='';c=getchar())x=x*+c-'';return x*=k;}
inline int find(int x){return x==f[x]?x:find(f[x]);}
void dfs(int s,int t,int rem){
if(rem==){
sum++;
return;
}
for(int i=s;i-+rem<=t;i++){
int fv=find(g[i].v),fu=find(g[i].u);
if(fu!=fv){
int F=f[fu];
f[fu]=fv;
dfs(i+,t,rem-);
f[fu]=F;
}
}
}
inline void solve(){
int i,j;
for(i=,j=;i<=m&&j<n;i++){
int fu=find(g[i].u),fv=find(g[i].v);
if(fu!=fv){
f[fu]=fv;
ect[b[i]]++;
j++;
}
}
if(j<n){
puts("");
return;
}
for(int i=;i<=n;i++) f[i]=i;
for(i=;i<=cnt;i++){
sum=;
dfs(a[i],a[i+]-,ect[i]);
for(int j=a[i];j<a[i+];j++){
int fu=find(g[j].u),fv=find(g[j].v);
if(fu!=fv) f[fu]=fv;
}
ans=(ans*sum)%mod;
}
printf("%d\n",ans);
}
inline void init(){
read(n); read(m);
for(int i=;i<=n;i++) f[i]=i;
for(int i=,u,v,w;i<=m;i++){
read(u); read(v); read(w);
g[i]=edge(u,v,w);
}
sort(g+,g++m);
for(int i=;i<=m;i++){
if(g[i].w!=g[i-].w) a[++cnt]=i;
b[i]=cnt;
}
a[cnt+]=m+;
}
int main(){
init();
solve();
return ;
}
1016: [JSOI2008]最小生成树计数
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4666 Solved: 1890
[Submit][Status][Discuss]
Description
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。
Input
第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整
数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,0
00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。
Output
输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
Sample Input
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1
Sample Output
HINT
Source
BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)的更多相关文章
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...
- 【BZOJ】【1016】【JSOI2008】最小生成树计数
Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的 ...
- [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】
题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...
- bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】
有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...
- BZOJ 1016 【JSOI2008】 最小生成树计数
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 【BZOJ1016】【JSOI2008】最小生成树计数
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- BZOJ_1833_[ZJOI2010]_数字计数_(数位dp)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1833 统计\(a~b\)中数字\(0,1,2,...,9\)分别出现了多少次. 分析 数位dp ...
随机推荐
- Java多线程练习:ticket卖票程序
/*需求:简单的卖票程序多个窗口买票 */ class Ticket extends Thread{ private static int tick=100; public void ru ...
- dubbo监控活跃线程数
telnet对应dubbo服务的ip+端口号 status -l 其中的active就是当前的活跃线程数 通过程序定时探测写入DB,再查询渲染出来就好了 监控报警,如果已经有监控平台,可以通过一定的规 ...
- 创建线程的两种方式比较Thread VS Runnable
1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...
- 转:基于IOS上MDM技术相关资料整理及汇总
一.MDM相关知识: MDM (Mobile Device Management ),即移动设备管理.在21世纪的今天,数据是企业宝贵的资产,安全问题更是重中之重,在移动互联网时代,员工个人的设备接入 ...
- 【HeadFirst设计模式】8.模板方法模式
模板方法 定义: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使用得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 策略模式: 定义一个算法家族,并让这些算法可以互 ...
- 安装eclipse中文汉化包后无法打开eclipse
通过在线安装中文汉化包后一直提示无法启动程序在.log中查看日志 !SESSION 2016-01-15 11:22:57.959 ---------------------------------- ...
- Json概述以及python对json的相关操作《转》
什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...
- linux内核启动参数
Linux内核启动参数 Console Options 参数 说明 选项 内核配置/文件 console=Options 用于说明输出设备 tt ...
- C#对word、excel、pdf等格式文件的操作总结
一.word 这是我以前工作时写过的一个业务逻辑处理类,里面有不少文件操作的方法,这里主要关注一下C#对word的操作.里面的方法可以直接拿出来用,主要是通过word的dot模版来进行创建word.替 ...
- 不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean
在百度搜“java反射 将表单数据自动封装到javabean ”,第一页显示的都是一样的代码,都是利用导入第三方jar包<commons-beanutils>和<commons-lo ...