【BZOJ】【1016】【JSOI2008】最小生成树计数
Kruskal/并查集+枚举
唉我还是too naive,orz Hzwer
一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的,再加上权值为2和2的,不也满足题意吗?事实上,如果这样的话……最小生成树应该是1和2,而不是1和3或2和2!!!
所以呢?所以对于一个图来说,最小生成树有几条边权为多少的边,都是固定的!所以我们可以做一遍Kruskal找出这些边权,以及每种边权出现的次数。然后,对于每种边权,比方说出现了$v_i$次,那么可以替换的一定是形成环的!且这种边权的选取方案对其他边权的没有影响,我就可以$2^{v_i}$枚举每条边是否选取,暴力找出这$v_i$条边的可行方案数,这个复杂度并不高,因为题目保证了这里的$v_i \leq 10$。
proverbs:
最小生成树的两个性质:
1、边权相等的边的个数一定。
2、做完边权为w的所有边时,图的连通性相同。
/**************************************************************
Problem: 1016
User: Tunix
Language: C++
Result: Accepted
Time:8 ms
Memory:1300 kb
****************************************************************/ //BZOJ 1016
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,INF=~0u>>,MOD=;
typedef long long LL;
/******************tamplate*********************/
int n,m,fa[N];
struct edge{int u,v,w;}e[];
struct data{int l,r,v;}a[];
bool cmp(edge a,edge b){return a.w<b.w;}
int Find(int x){return fa[x]==x?x:Find(fa[x]);}
int sum,ans=,tot;
void dfs(int x,int now,int k){
if (now==a[x].r+){
if (k==a[x].v) sum++;
return;
}
int p=Find(e[now].u),q=Find(e[now].v);
if (p!=q){
fa[p]=q;
dfs(x,now+,k+);
fa[p]=p; fa[q]=q;
}
dfs(x,now+,k);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1016.in","r",stdin);
freopen("1016.out","w",stdout);
#endif
n=getint(); m=getint();
F(i,,m){
e[i].u=getint(); e[i].v=getint(); e[i].w=getint();
}
sort(e+,e+m+,cmp);
int cnt=,now=;
F(i,,n) fa[i]=i;
F(i,,m){
if (i==||e[i].w!=e[i-].w) {a[++cnt].l=i;a[cnt-].r=i-;}
int p=Find(e[i].u),q=Find(e[i].v);
if (p!=q){ fa[p]=q; a[cnt].v++; tot++;}
}
a[cnt].r=m;
if (tot!=n-){puts("");return ;}
F(i,,n) fa[i]=i;
F(i,,cnt){
sum=;
dfs(i,a[i].l,);
ans=ans*sum%MOD;
F(j,a[i].l,a[i].r){
int p=Find(e[j].u),q=Find(e[j].v);
if (p!=q) fa[p]=q;
}
}
printf("%d\n",ans);
return ;
}
1016: [JSOI2008]最小生成树计数
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3312 Solved: 1311
[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,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】最小生成树计数的更多相关文章
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
- [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】
题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...
- [BZOJ]1016 JSOI2008 最小生成树计数
最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...
- 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 ...
- 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集
最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...
随机推荐
- apache日志文件详解和实用分析命令
apache日志文件每条数据的请意义,以及一些实用日志分析命令. 一.日志分析 如果apache的安装时采用默认的配置,那么在/logs目录下就会生成两个文件,分别是access_log和error ...
- shell脚本入门
什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_tut for ((i=0; i<10; i++)); do touch ...
- PHP判断用户所在国家并跳转对应的目录
<?php // 淘宝API查询国家代码 $url = "http://ip.taobao.com/service/getIpInfo.php?ip=".get_client ...
- 往Android SDCard中读写入数据
一.用Environment (写) 1.API获取sdcard的路径 File path=Environment.getExternalStorageDirectory(); path=new Fi ...
- 通过messenger实现activity与service的相互通信
布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:to ...
- Android———从GitHub上下载源码的方法【Written By KillerLegend】
首先声明,本文说的是从GitHub上下载源码而非上传源码! 1:下载tortoisegit,下载地址为: https://code.google.com/p/tortoisegit/wiki/Down ...
- 【坑】log4j-over-slf4j.jar AND slf4j-log4j12.jar的冲突问题
为了解决这个问题,已经有砸电脑的冲动了.通过百度查找都说是Maven依赖的原因,经过各种尝试仍然没有解决,后来终于在QQ群的帮助下,算是暂时过关. [问题] 程序在本地运行没有问题,打成jar包发布到 ...
- .NET设计模式系列文章 from TerryLee
http://www.cnblogs.com/Terrylee/archive/2006/07/17/334911.html 最初写探索设计模式系列的时候,我只是想把它作为自己学习设计模式的读书笔记来 ...
- Python脚本控制的WebDriver 常用操作 <十> 层级定位
下面将使用WebDriver来模拟操作一个层级定位元素的操作 测试用例场景 在实际的项目测试中,经常会有这样的需求:页面上有很多个属性基本相同的元素,现在需要具体定位到其中的一个.由于属性基本相当,所 ...
- C/C++ 内存管理 (《高质量C++》-- 整理笔记)
内存管理是我们在编程时经常遇到的问题,而关于内存管理的问题往往会导致我们无从下手,这篇随笔是我阅读<高质量C++>第7章“内存管理”时一些总结. 1.内存分配方式 在C++中内存分为5个区 ...