1016: [JSOI2008]最小生成树计数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 6200  Solved: 2518
[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

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

Sample Output

8
/*
* @Author: LyuC
* @Date: 2017-09-07 21:48:20
* @Last Modified by: LyuC
* @Last Modified time: 2017-09-12 17:52:51
*/
/*
题意:现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道
这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则
这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方
案数对31011的模就可以了。 思路:每个最小生成树的相同权值的边数是相同的,并且连通性是相同的,只需要枚举每个
权值的相同连通性,并且是最小生成树中这个权值的个数的方案数,然后组合一下就行了
*/
#include <bits/stdc++.h> #define MAXN 105
#define MAXM 1005
#define mod 31011 using namespace std; struct Edge{
int u,v,w;
bool operator < (const Edge & other) const{
return w<other.w;
}
}edge[MAXM];
vector<Edge>v[MAXM];
int n,m;
int x,y,z;
int bin[MAXN];
int root[MAXN];
int vis[MAXM];//每种权值用到的数量
int sum;
int la;
int pos;
int res; inline int findx(int x){
int s=x;
while(x!=bin[x])
x=bin[x];
bin[s]=x;
return x;
} inline int Count(int x){
int s=;
while(x){
if(x%)
s++;
x/=;
}
return s;
} inline void init(){
for(int i=;i<=n;i++){
bin[i]=i;
root[i]=i;
}
memset(vis,,sizeof vis);
for(int i=;i<MAXM;i++)
v[i].clear();
res=;
pos=;
sum=;
} int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
init();
for(int i=;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
edge[i].u=x;
edge[i].v=y;
edge[i].w=z;
}
sort(edge,edge+m);
//处理每种权值需要的边数
la=-;
for(int i=;i<m;i++){
if(edge[i].w!=la){
la=edge[i].w;
bool flag=false;
for(int j=i;edge[j].w==la;j++){
int fx=findx(edge[j].u);
int fy=findx(edge[j].v);
if(fx!=fy){
flag=true;
bin[fx]=fy;
vis[pos]++;
sum++;
}
v[pos].push_back(edge[j]);
}
pos++;
}
}
if(sum!=n-){
puts("");
return ;
}
for(int i=;i<pos;i++){//枚举每个阶段用到权值的边
if(vis[i]==) continue;
int tol=(<<v[i].size());
int cur=;//可以的方案
for(int j=;j<tol;j++){
if(Count(j)!=vis[i]) continue;
bool flag=true;
memcpy(bin,root,sizeof root);
for(int k=;k<v[i].size();k++){
if((j&(<<k))!=){//如果这条边存在
int fx=findx(v[i][k].u);
int fy=findx(v[i][k].v);
if(fx==fy){
flag=false;
break;
}else{
bin[fx]=fy;
}
}
}
if(flag==true)
cur++;
}
res=res*cur%mod;
memcpy(bin,root,sizeof root);
for(int j=;j<v[i].size();j++){
int fx=findx(v[i][j].u);
int fy=findx(v[i][j].v);
if(fx!=fy){
bin[fx]=fy;
}
}
memcpy(root,bin,sizeof bin);
}
printf("%d\n",res%mod);
return ;
}

1016: [JSOI2008]最小生成树计数的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

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

  5. 【BZOJ】1016: [JSOI2008]最小生成树计数(kruskal+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 想也想不到QAQ 首先想不到的是:题目有说,具有相同权值的边不会超过10条. 其次:老是去想组 ...

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

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

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

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

  8. 大视野 1016: [JSOI2008]最小生成树计数(最小生成树)

    总结:此类题需要耐心观察规律,大胆猜想,然后证明猜想,得到有用的性质,然后解答. 简单的说:找隐含性质. 传送门:http://61.187.179.132/JudgeOnline/problem.p ...

  9. 1016: [JSOI2008]最小生成树计数 - BZOJ

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

随机推荐

  1. js转换字符串为数值的方法

    在js读取文本框或者其他表单数据的时候获得的值是字符串类型的,比如两个文本框a和b,假设获得a的value值为11,b的value值为9 ,那么a.value要小于b.value,由于他们都是字符串形 ...

  2. MySQL主从同步和读写分离的配置

    主服务器:192.168.1.126 从服务器:192.168.1.163 amoeba代理服务器:192.168.1.237 系统全部是CentOS 6.7 1.配置主从同步 1.1.修改主服务器( ...

  3. U方法

    U方法用于完成对URL地址的组装,特点在于可以自动根据当前的URL模式和设置生成对应的URL地址,格式为:U('地址','参数','伪静态','是否跳转','显示域名');在模板中使用U方法而不是固定 ...

  4. JS 数据处理技巧及小算法汇总( 一)

    前言: 金秋九月的最后一天,突然发现这个月博客啥也没更新,不写点什么总觉得这个月没啥长进,逆水行舟,不进则退,前进的路上贵在坚持,说好的每个月至少一到两篇,不能半途而废!好多知识写下来也能加深一下自身 ...

  5. Spark sql ---JSON

    介绍Spark SQL的JSON支持,这是我们在Databricks中开发的一个功能,可以在Spark中更容易查询和创建JSON数据.随着网络和移动应用程序的普及,JSON已经成为Web服务API以及 ...

  6. 基于NodeJS进行前后端分离

    1.什么是前后端分离 传统的SPA模式:所有用到的展现数据都是后端通过异步接口(AJAX/JSONP)的方式提供的,前端只管展现. 从某种意义上来说,SPA确实做到了前后端分离,但这种方式存在两个问题 ...

  7. Dynamic Inversions 50个树状数组

    Dynamic Inversions Time Limit: 30000/15000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others ...

  8. java基础(Fundamental)

    第一节 java开发环境 1.Linux操作系统 1)开源的操作系统.免费,主要作为服务器操作系统, 而Java主要是服务器端开发,所以部署环境都是Linux 2)Linux与Windows目录结构的 ...

  9. 原生JS封装animate运动框架

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  10. 机器学习技法:01 Linear Support Vector Machine

    Roadmap Course Introduction Large-Margin Separating Hyperplane Standard Large-Margin Problem Support ...