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
 
 
正解:克鲁斯卡尔最小生成树+搜索
解题报告:
  今天考场上考了一道这个题目,我居然没看出来就是一道求最小生成树个数的裸题。。。
  说起来还是挺水的,就是有许多性质还掌握的不够熟练。不同的最小生成树方案,每种权值的边的数量是确定的,每种权值的边的作用是确定的。所以每种权值看作一个集合,这个集合若想对最终结果产生贡献,即是最小生成树,需要选取的边数是固定的。

  排序以后先做一遍最小生成树,得出每种权值的边使用的数量x

  然后对于每一种权值的边搜索,得出每一种权值的边选择方案。就是枚举某条边选不选,暴力搜索是否可行。(因为题目说同种权值不超过10,所以指数级大暴力不虚)

  最后乘法原理,每一步的方案数相乘。

 
 
 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
const int MAXM = ;
const int MOD = ;
int n,m;
int first[MAXN],next[MAXM],to[MAXM];
int cnt;
int father[MAXN];
int ans,lin; struct build{
int l,r,cnt;
}a[MAXM]; struct edge{
int x,y,z;
}e[MAXM]; inline 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;
} inline bool cmp(edge q,edge qq){ return q.z<qq.z; } inline int find(int x){
//不能路径压缩!!!
if(father[x]!=x) return find(father[x]); //father[x]=find(father[x]);
return father[x];
} inline void dfs(int x,int now,int gong){
if(now==a[x].r+) {
if(gong==a[x].cnt) lin++;//必须选指定的条数
return ;
}
int r1=find(e[now].x),r2=find(e[now].y);
if(r1!=r2) {//枚举选还是不选
father[r1]=r2;
dfs(x,now+,gong+);
father[r1]=r1; father[r2]=r2;
}
dfs(x,now+,gong);//不选
} inline void solve(){
n=getint(); m=getint();
int x,y,z;
for(int i=;i<=m;i++) {
x=getint(); y=getint(); z=getint();
e[i].x=x; e[i].y=y; e[i].z=z;
} sort(e+,e+m+,cmp); for(int i=;i<=n;i++) father[i]=i; int gg=;
for(int i=;i<=m;i++) {
if(e[i].z!=e[i-].z) { cnt++; a[cnt].l=i; a[cnt-].r=i-; }
int r1=find(e[i].x),r2=find(e[i].y);
if(r1!=r2) {
father[r2]=r1;
a[cnt].cnt++;
gg++;
//if(gg==n-1) break;
}
}
a[cnt].r=m; if(gg!=n-) { printf(""); return ; }
for(int i=;i<=n;i++) father[i]=i; ans=;
for(int i=;i<=cnt;i++) {
lin=;
dfs(i,a[i].l,);
ans*=lin; if(ans>=MOD) ans%=MOD; for(int j=a[i].l;j<=a[i].r;j++) {
int r1=find(e[j].x),r2=find(e[j].y);
if(r1!=r2) father[r2]=r1;
}
} printf("%d",ans);
} int main()
{
solve();
return ;
}

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

  1. BZOJ1016最小生成树计数 最小生成树 + 排列组合

    @[最小生成樹, 排列組合] Discription 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的 最小生成树.(如果两颗最小生成树中至少有一条边不 ...

  2. 【bzoj1016】 JSOI2008—最小生成树计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 (题目链接) 题意 求图的最小生成树计数. Solution %了下题解,发现要写矩阵树,15 ...

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

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

  4. 【bzoj1016】[JSOI2008]最小生成树计数

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

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

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

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

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

  7. 最小生成树计数 bzoj 1016

    最小生成树计数 (1s 128M) award [问题描述] 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一 ...

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

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

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

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

随机推荐

  1. Android View坐标getLeft, getRight, getTop, getBottom

    1  引起疑惑 分析视图invalidate流程的过程中发现view的left, right, top, bottom跟自己理解的不一样,现在想分析一下这几个值具体的含义. 2  理解坐标,位置概念 ...

  2. python中的Unittest常用方法

    import unittest class SimpleUnitTest(unittest.TestCase): def test_Fail(self): self.failUnless(True) ...

  3. IIS mime类型

    参考网站:http://www.iwms.net/n1381c2.aspx 以下例子为iis6.0 下载安卓.苹果安装包时候,需要添加mime类型才可以下载,否则访问不到 安卓 .apk  appli ...

  4. ajax读取文本内容(此处的txt文件和html文件处于同级目录)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <style&g ...

  5. php基础25:each()

    <?php /* 返回当前元素的键名和键值,并将内部指针向前移动: */ $people = array("Bill", "Steve", "M ...

  6. 实现可以滑动的GrildView,类似美团网首页的GrildView功能菜单

    首先上实现效果图,不会做动态图,就先凑合着看吧 使用了网上的一个开源控件viewpagerindicator,可以自定义切换时候显示的标记,圆点,或者下划线. GrildView显示的是手机上的全部a ...

  7. Java系列:JVM指令详解(下)(zz)

    九.自增减指令    20:iconst_1    21:istore_1    22:return 指令码      助记符                                     ...

  8. [CareerCup] 8.3 Musical Jukebox 点唱机

    8.3 Design a musical jukebox using object-oriented principles. CareerCup这书实在是太不负责任了,就写了个半调子的程序,说是完整版 ...

  9. [CareerCup] 10.7 Simplified Search Engine 简单的搜索引擎

    10.7 Imagine a web server for a simplified search engine. This system has 100 machines to respond to ...

  10. [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝

    13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...