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,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过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

Solution

对于不同的MST方案,相同权值的边数总是一定。因此我们可以排序后先跑一次MST并离散权值,统计出每种权值被用了多少次,然后对于每种权值暴力枚举各条边是否使用,检查合法性以及使用边数是否等于原本所使用的,乘法原理一下即可,由于有撤销操作不能够压缩路径,因此建议采用启发式合并。

时间复杂度\(O(E \log_2 E + \Sigma 2^{cnt_{v}} * \log_{2} V)\)其中\(cnt_{v}\)表示权值v在MST中的使用次数。

Code

#include <stdio.h>
#include <algorithm>
#define MN 105
#define MM 1005
#define R register
#define mod 31011
inline int read(){
R int x; R bool f; R char c;
for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
return f?-x:x;
}
int V,E,cnt,val[MM],x[MM],y[MM],rk[MM],l[MM],r[MM],v[MM],fa[MN],sz[MN],sum,ans=1,k;
inline bool cmp(int x,int y){return val[x]<val[y];}
inline int find(int x){return fa[x]==x?x:find(fa[x]);}
inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
inline void ins(int x,int y){
if (sz[x]<sz[y]) swap(x,y);
fa[y]=x;sz[x]+=sz[y];
}
inline void del(int x,int y){
if (fa[x]==y) swap(x,y);
fa[y]=y; sz[x]-=sz[y];
}
inline void dfs(int t,int no,int k){
if (no>r[t]){
sum+=(k==v[t]);
return;
}R int p=find(x[rk[no]]),q=find(y[rk[no]]);
if (p!=q){
ins(p,q);dfs(t,no+1,k+1);del(p,q);
}dfs(t,no+1,k);
}
int main(){
V=read(),E=read();for (R int i=1; i<=E; ++i) x[i]=read(),y[i]=read(),val[i]=read(),rk[i]=i;
std::sort(rk+1,rk+E+1,cmp);for (R int i=1; i<=V; ++i) fa[i]=i;
for (R int i=1; i<=E; ++i){
if (val[rk[i]]!=val[rk[i-1]]) {r[cnt]=i-1; if (k==V-1) break;l[++cnt]=i;}
R int p=find(x[rk[i]]),q=find(y[rk[i]]);
if (p!=q){ins(p,q);++v[cnt],++k;}
}if (!r[cnt]) r[cnt]=E;if (k!=V-1){puts("0");return 0;}for (R int i=1; i<=V; ++i) fa[i]=i;
for (R int i=1; i<=cnt; ++i){
sum=0;dfs(i,l[i],0);ans=ans*sum%mod;
for (R int j=l[i]; j<=r[i]; ++j){
R int p=find(x[rk[j]]),q=find(y[rk[j]]);
if (p!=q) ins(p,q);
}
}printf("%d\n",ans);
return 0;
}

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

  1. bzoj1016 [JSOI2008]最小生成树计数

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

  2. bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)

    1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等  就是说如果一种方案中权值为1的边有n条 ...

  3. BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)

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

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

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

  5. 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数

    题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...

  6. [BZOJ1016][JSOI2008]最小生成树计数(结论题)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...

  7. [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)

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

  8. 【最小生成树】BZOJ1016: [JSOI2008]最小生成树计数

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

  9. 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)

    传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...

  10. [BZOJ1016][JSOI2008]最小生成树计数 最小生成树 搜索

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1016 做这道题之前需要知道一些结论,同一个图的最小生成树中相同权值的边的个数是不会变的,如 ...

随机推荐

  1. Python 线程复习

    修改全局变量,设立flag来避免线程间数据冲突,低效率版 from threading import Thread import time g_num=0 g_flag = 1 def test1() ...

  2. hashlib 加密

    import hashlib def md5(args): hash = hashlib.md5(bytes('aaadf',encoding='utf-8')) hash.update(bytes( ...

  3. TOTP算法 基于时间的一次性密码

    /** Copyright (c) 2011 IETF Trust and the persons identified as authors of the code. All rights rese ...

  4. wpf研究之道——datagrid控件数据绑定

    前台: <DataGrid x:Name="TestCaseDataGrid" ItemsSource="{Binding}" > {binding ...

  5. JAVA工程师面试题【来自并发编程网】

    基础题: Java线程的状态 进程和线程的区别,进程间如何通讯,线程间如何通讯 HashMap的数据结构是什么?如何实现的.和HashTable,ConcurrentHashMap的区别 Cookie ...

  6. mosquitto验证client互相踢

    cleint11A订阅topic#################################################### server发送topic消息 ############### ...

  7. NHibernate与IbatisNet的简单比较

    NHibernate是当前最流行的Java O/R mapping框架Hibernate的移植版本,当前版本是1.0 rc-1.它出身于sf.net..IbatisNet是另外一种优秀的Java O/ ...

  8. power designer 连接mysql提示“connection test failed”

    本机环境: win10 64位 jdk8 64位 问题: 测试连接时,总是提示 根据网上搜索: 根源在于:PowerDesigner based on 32 bit JVM kernel 参考: ht ...

  9. windows系统设置虚拟机开机自启并运行虚拟系统

    简述 很多用windows系统电脑开发的童鞋,会在自己电脑上装一个虚拟机,然后在装一个linux系统当作服务器来使用. 但每次电脑开机都要去重启一下虚拟机电源,实在是不划算.下面博主教大家在windo ...

  10. 【VB超简单入门】四、编译工程及传播程序文件

    四.编译工程及传播程序文件 为什么在这一章中讲到编译这部分内容呢?因为当我们学会怎样用VB开发程序之后,内心肯定喜悦无比.这时候就要和朋友分享一下快乐,所以要先学习编译EXE程序文件. 首先新建工程. ...