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

4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1

Sample Output

8
 

  这一次居然自己想出来了一道还算比较难的题,心里好开心O(∩_∩)O~~

  这道题用到了最小生成树的几个性质。第一,最小生成树每种边权的边数量一定。第二(由第一点可得),当一个图有多个最小生成树时,只可能由一条边替换掉一条等边权的边来得到一颗新的最小生成树。所以,注意到题目中的一个条件:

  具有相同权值的边不会超过10条。

  所以我们就非常地开心。因为这样就可以做了。我们把边按权值排序,然后对于每一块权值相同的边搜索哪些边要选,再统计一下方案数就可以AC辣!

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 5010
#define INF (1LL<<50)
#define mod 31011 using namespace std;
typedef long long llg; struct data{
int u,v,x;
bool operator < (const data &h)const{return x<h.x;}
}s[maxn];
struct dat1{
int l,r,x;
dat1(int a=,int b=,int c=):l(a),r(b),x(c){};
}ss[maxn];
int n,m,fa[maxn],ls,la[maxn],w[maxn];
llg ans=INF,a1,now,aa=;
bool ww[maxn]; int getint(){
int w=,q=;
char c=getchar();
while((c<''||c>'')&&c!='-') c=getchar();
if(c=='-') q=,c=getchar();
while(c>=''&&c<='') w=w*+c-'',c=getchar();
return q?-w:w;
} int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} inline void work(){
now=;int k=;
for(int i=;i<=n;i++) fa[i]=i;
for(int i=,u,v;i<=m;i++)
if(ww[i]){
u=s[i].u;v=s[i].v;
if(find(u)!=find(v)){
now+=s[i].x; k++;
fa[find(u)]=find(v);
}
}
if(k!=n-) return;
if(now<ans) ans=now,a1=;
else if(now==ans) a1++;
} void dfs(int res,int now,int dd){
if(now==dd+){
work();return;
}
if(res){
ww[now]=;
dfs(res-,now+,dd);
}
if(dd-now+>res){
ww[now]=;
dfs(res,now+,dd);
}
} int main(){
n=getint();m=getint();
for(int i=;i<=m;i++){
s[i].u=getint();s[i].v=getint();
s[i].x=getint();
}
sort(s+,s+m+);
for(int i=;i<=n;i++) fa[i]=i;
for(int i=,u,v;i<=m;i++){
w[i]=w[i-]; ww[i]=;
la[i]=i; u=s[i].u;v=s[i].v;
if(s[i-].x==s[i].x) la[i]=la[i-];
if(find(u)!=find(v)){
now+=s[i].x; w[i]++;
fa[find(u)]=find(v);
}
if(la[i]!=i && s[i+].x!=s[i].x)
ss[++ls]=dat1(la[i],i,w[i]-w[la[i]-]);
}
for(int i=;i<=ls;i++){
ans=INF;
dfs(ss[i].x,ss[i].l,ss[i].r);
for(int j=ss[i].l;j<=ss[i].r;j++) ww[j]=;
aa*=a1; aa%=mod;
}
ans%=mod; aa%=mod;
printf("%lld",aa);
return ;
}

BZOJ 1016 【JSOI2008】 最小生成树计数的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

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

随机推荐

  1. UI中一些不常用的控件UIActivityIndicatorView、UIProgressView、UISegmentedControl、UIStepper、UISwitch、UITextView、UIAlertController

    //UIActivityIndicatorView //小菊花,加载 #import "ActivityIndicatorVC.h" @interface ActivityIndi ...

  2. 开启Apache mod_rewrite模块完全解答

    启用mod_rewrite模块 在conf目录的httpd.conf文件中找到 LoadModule rewrite_module modules/mod_rewrite.so 将这一行前面的#去掉. ...

  3. js去掉字符串前后空格的五种方法

    转载 :http://www.2cto.com/kf/201204/125943.html 第一种:循环检查替换[javascript]//供使用者调用  function trim(s){  ret ...

  4. tomcat常见错误及解决方案

    一,tomcat启动时错误 1:The JAVA_HOME environment variable is not defined This environment variable is neede ...

  5. Node异步I/O、事件驱动与高性能服务器

    事件循环.观察者.请求对象.I/O线程池这四者共同构成了Node异步I/O模型的基本要素. 异步I/O流程:

  6. 学习 MySQL-DBA常用SQL汇总

    创建用户 GRANT USAGE ON *.* TO 'rp'@'%' IDENTIFIED BY 'rp' MAX_UPDATES_PER_HOUR MAX_CONNECTIONS_PER_HOUR ...

  7. 个人作业week-1-14061195

    软件: 根据维基百科, The first theory about software—prior to creation of computers as we know them today—was ...

  8. 1、开篇:PMO定义 - PMO项目管理办公室

    PMO,Project Management Office,项目管理办公室,笔者不按照项目管理知识体系指南PMBOK(Project Management Body Of Knowledge)上的定义 ...

  9. lnmp之php5.3.27 编译信息

    ./configure \--prefix=/application/php5.3.27 --with-mysql=application/mysql \--with-iconv-dir=/usr/l ...

  10. php截取字符串函数

    public function sub_string($str, $len, $charset="utf-8") { if( !is_numeric($len) or $len & ...