【BZOJ】1016: [JSOI2008]最小生成树计数(kruskal+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=1016
想也想不到QAQ
首先想不到的是:题目有说,具有相同权值的边不会超过10条。
其次:老是去想组合计数怎么搞。。。。。。。于是最sb的暴力都不会了。。
所以这题暴力搞就行了orz
依次加边,每一种边的方案数乘起来就是方案了。
注意并查集不能路径压缩,否则在计数的时候会waQAQ因为并查集的路径压缩是不可逆的QAQ
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mkpii make_pair<int, int>
#define pdi pair<double, int>
#define mkpdi make_pair<double, int>
#define pli pair<ll, int>
#define mkpli make_pair<ll, int>
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=105, M=1005, MD=31011;
int n, m, cnt, p[N], ans=1, sum;
struct dat { int x, y, w; }e[M], a[M];
inline const bool cmp(const dat &a, const dat &b) { return a.w<b.w; }
inline const int ifind(const int &x) { return x==p[x]?x:ifind(p[x]); } void dfs(int now, int s, const int &x) {
if(now>a[x].y) {
if(s==a[x].w) ++sum;
return;
}
dfs(now+1, s, x);
int fx=ifind(e[now].x), fy=ifind(e[now].y);
if(fx!=fy) { p[fx]=fy; dfs(now+1, s+1, x); p[fx]=fx; p[fy]=fy; }
} int main() {
read(n); read(m);
for1(i, 1, m) read(e[i].x), read(e[i].y), read(e[i].w);
for1(i, 1, n) p[i]=i;
sort(e+1, e+1+m, cmp);
int ed=0;
for1(i, 1, m) {
if(e[i].w!=e[i-1].w) a[++cnt].x=i, a[cnt-1].y=i-1;
int fx=ifind(e[i].x), fy=ifind(e[i].y);
if(fx!=fy) {
p[fx]=fy;
++a[cnt].w;
++ed;
}
}
if(ed!=n-1) { puts("0"); return 0; }
a[cnt].y=m;
for1(i, 1, n) p[i]=i;
for1(i, 1, cnt) {
sum=0;
dfs(a[i].x, 0, i);
ans=(ans*sum)%MD;
for1(j, a[i].x, a[i].y) {
int fx=ifind(e[j].x), fy=ifind(e[j].y);
if(fx!=fy) p[fx]=fy;
}
}
print(ans); return 0;
}
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
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1
Sample Output
HINT
Source
【BZOJ】1016: [JSOI2008]最小生成树计数(kruskal+特殊的技巧)的更多相关文章
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
- [BZOJ]1016 JSOI2008 最小生成树计数
最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...
- [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】
题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...
- BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)
题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...
- bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...
- bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】
有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...
- BZOJ 1016 [JSOI2008]最小生成树计数 ——Matrix-Tree定理
考虑从小往大加边,然后把所有联通块的生成树个数计算出来. 然后把他们缩成一个点,继续添加下一组. 最后乘法原理即可. 写起来很恶心 #include <queue> #include &l ...
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...
- 1016: [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6200 Solved: 2518[Submit][St ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
随机推荐
- Laravel 教程 - Web 开发实战入门 ( Laravel 5.5 )购买链接
Laravel 教程 - Web 开发实战入门 ( Laravel 5.5 )购买链接: 推荐给你高品质的实战课程 https://laravel-china.org/courses?rf=158 ...
- Jquery重新学习之五[操作JSON数据]
Jquery操作Json格式的数据在我们平时的项目中也经常运用:最近看Jquery权威指南中就有一章节是对这方面的整理总结:最后通过一个Asp.net结合一般处理程序ashx的实例,基本上能满足项目中 ...
- 【剑指offer】面试题30:最小的K个数
import random def partition(data, start, end): if end <= start: return start index = random.randi ...
- Linux中内存挂载到目录下
[日期:2012-11-14] /dev/shm是linux下的一块共享内存结构.默认大小是真实内存的一半.它用来存储进程间通讯时的一些共享数据结构.在物理内存足够时,会在内存中进行数据交换,如果 ...
- 探索Python F-strings是如何工作
PEP 498 提出一种新型字符串格式化机制,被称为“字符串插值”或者更常见的一种称呼是F-strings(主要因为这种字符串的第一个字母是f).F-strings提供了一种明确且方便的方式将pyth ...
- C#:Ini文件操作(待补充)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...
- VC++编写ActiveX控件
ActiveX这门技术是通过生成“*.ocx”文件来实现的.先来了解下OCX文件,在百度百科上面对OCX是这样解释的:“.ocx是ocx控件的扩展名,OCX 是对象类别扩充组件.如果你用过Visual ...
- STL中map错误用法一例
[GBK]0G's fans( me ) 13:34:26typedef struct _TX_DATA{ int len; unsigned char buff[0x100]; } TX_DATA, ...
- MYSQL服务器复制配置
首先声明:此文是在失去U盘极度郁闷的时候写的,有些零散,估计也有错误.欢迎大家指出 MYSQL服务器复制配置 这是根据我之前看的MYSQL复制的文档然后自己亲自实验的过程.配置的功能比较简单. ...
- UVA - 1218 Perfect Service(树形dp)
题目链接:id=36043">UVA - 1218 Perfect Service 题意 有n台电脑.互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连 ...