https://www.lydsy.com/JudgeOnline/problem.php?id=1016

现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。

无外乎两种:K算法和P算法(当然还有第三种但是我不会(滑稽)

P算法没法解于是用K算法。

发现K算法的正确性后其实我们需要做的工作就是从K算法找到一些边,可以用另一些边权一样的边替换并且是一棵生成树即可。

于是我们枚举即可。

(当然你会有两个问题:1.为什么边权一样即可替换,2.前面的边的操作对后面边是否有影响?)

(所以暴力选手不过脑子的话就很轻松的敲完代码走人了(比如我))

(实际为两个定理,分别为:

1.不同的最小生成树中,每种权值的边出现的个数是确定的。

2.不同的生成树中,某一种权值的边连接完成后,形成的联通块状态是一样的 。

百度一下。)

https://blog.csdn.net/jarily/article/details/8902402可能这个解释靠谱些?)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=;
const int M=;
const int p=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int u,v,w;
}e[M];
struct range{
int l,r;
}a[M];
int fa[N],t[M],n,m,k,sum;
inline bool cmp(node a,node b){
return a.w<b.w;
}
int find(int x){
if(fa[x]==x)return x;
return find(fa[x]);
}
inline void unionn(int x,int y){
fa[x]=y;
}
inline void destory(int x,int y){
fa[x]=x;fa[y]=y;
}
void dfs(int l,int r,int d,int w){
if(l>r){
if(d==t[w])sum=(sum+)%p;
return;
}
if(r-l++d<t[w])return;
int u=find(e[l].u),v=find(e[l].v);
if(u!=v&&d<t[w]){
unionn(u,v);
dfs(l+,r,d+,w);
destory(u,v);
}
dfs(l+,r,d,w);
}
int main(){
n=read(),m=read();
for(int i=;i<=m;i++){
e[i].u=read(),e[i].v=read(),e[i].w=read();
}
sort(e+,e+m+,cmp);
for(int i=;i<=n;i++)fa[i]=i;
int cnt=;
for(int i=;i<=m;i++){
if(e[i].w!=e[i-].w){
a[++k].l=i;a[k-].r=i-;
}
int u=e[i].u,v=e[i].v;
u=find(u),v=find(v);
if(u!=v)t[k]++,cnt++,unionn(u,v);
}
a[k].r=m;
if(cnt!=n-){
puts("");return ;
}
int ans=;
for(int i=;i<=n;i++)fa[i]=i;
for(int i=;i<=k;i++){
if(!t[i])continue;
sum=;
dfs(a[i].l,a[i].r,,i);
ans=(ll)ans*sum%p;
for(int j=a[i].l;j<=a[i].r;j++){
int u=e[j].u,v=e[j].v;
u=find(u),v=find(v);
if(u!=v)unionn(u,v);
}
}
printf("%d\n",ans);
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

BZOJ1016:[JSOI2008]最小生成树计数——题解的更多相关文章

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

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

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

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

  3. BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)

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

  4. [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)

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

  5. 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数

    题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...

  6. [BZOJ1016][JSOI2008]最小生成树计数(结论题)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...

  7. [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)

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

  8. 【最小生成树】BZOJ1016: [JSOI2008]最小生成树计数

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

  9. 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)

    传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...

随机推荐

  1. Linux 下获取本机IP

    http://blog.csdn.net/K346K346/article/details/48231933 int main () { /* struct ifaddrs *ifap, *ifa; ...

  2. Windows Server 2008 R2 安装域

    在Windows Server 2008 R2里面安装域. 1.首先在"服务"里面添加"角色": 2.选择对应的域角色 3.安装完成后要启动配置向导 4.选择新 ...

  3. 使用materialization

    explain select `countries`.`id` AS `id`,`countries`.`sortname` AS `sortname`,`countries`.`name` AS ` ...

  4. javaweb(九)—— 通过Servlet生成验证码图片

    一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedImage类,如下:

  5. 初识c++模板元编程

    模板元编程(Template metaprogramming,简称TMP)是编译器内执行的程序,编译器读入template,编译输出的结果再与其他源码一起经过普通编译过程生成目标文件.通俗来说,普通运 ...

  6. OpenSUSE 11 安装Qt5.0,失败,失败,失败,留个坑,以后来填,万一实现了呢

    我又来无耻的写问题来了,这次还真的是没有解决,线留坑吧,万一以后实现了. 同样,这次也是以恶搞网友说听说想在open suse 上面安装5.0版本以后的Qt,自己折腾好几没有成功. 我一想,哎,这不是 ...

  7. 只写Python一遍代码,就可以同时生成安卓及IOS的APP,真优秀

    前言: 用Python写安卓APP肯定不是最好的选择,但是肯定是一个很偷懒的选择 我们使用kivy开发安卓APP,Kivy是一套专门用于跨平台快速应用开发的开源框架,使用Python和Cython编写 ...

  8. OpenPAI大规模人工智能平台安装部署文档

    环境要求: 如果需要图形界面,需要在Ubuntu系统安装,否则centos系统安装时是没有问题的(web端和命令行进行任务提交) 安装过程需要有另外一台控制端机器(注意:区别于集群所在的任何一台服务器 ...

  9. Thunder团队第三周 - Scrum会议1

    Scrum会议1 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 杨梓瑞在拍照,所以不在照片中. 参会成员: 王航(Master):http://www.c ...

  10. C# .net 获取外网ip

    public string GetIP() { string strUrl = "http://www.ip138.com/ip2city.asp"; //获得IP的网址了 Uri ...