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. oracle数据中记录被另一个用户锁住

    原因:PL/SQL里面执行语句执行了很久都没有结果,于是中断执行,于是就直接在上面改字段,在点打钩(记入改变)的时候提示,记录被另一个用户锁住. 解决方法: 第一步:(只是用于查看哪些表被锁住,真正有 ...

  2. maven编译时错误:无效的目标发行版

    (转)Maven 将依赖打进一个jar包 博客分类: maven   maven配置 <?xml version="1.0" encoding="UTF-8&quo ...

  3. Treblecross 博弈SG值

    Treblecross is a two player game where the goal is to get three X in a row on a one-dimensional boar ...

  4. httpd日志和日志轮替工具

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...

  5. socket及其相关(续篇)

    IO 多路复用 基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口), ...

  6. 英特尔:不再公布PC处理器多核睿频数据

    据了解,以往英特尔官方有三个频率数据:基础主频:Turbo 2.0(多核)频率:以及Turbo 3.0(单核)频率.现在被隐匿的则是Turbo 2.0(多核)频率. 对此,英特尔在回应媒体时表示,给出 ...

  7. Python自学笔记-面向对象相关(Mr seven)

    ---恢复内容开始--- http://www.cnblogs.com/wupeiqi/articles/5433893.html 类的成员可以分为三大类:字段.方法和属性. 一.字段 字段包括:普通 ...

  8. C#中 计时器用法

    有时候我们会需要计算某段代码运行的时间比如一个sql查询,记录一段代码所花费的时间等等代码如下: System.Diagnostics.Stopwatch watch = new System.Dia ...

  9. 将图标LOGO之类的图形图像转换成字体调用方法大全

    借鉴百度对此标题的评价: 使用字体图标的优势 字体图标除了图像清晰度之外,比位图还有哪些优势呢. 适用性:一个图标字体比一系列的图像(特别是在Retina屏中使用双倍大小的图像)要小.一旦图标字体加载 ...

  10. List之Union(),Intersect(),Except() 即并集,交集,差集运算。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...