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. zedboard学习第一篇

    1. 刚开始学习使用,不知道从哪里开始,手上的资料也很乱,至于这个板子需要学什么也不清楚. 2. 第一个工程就从helloworld开始吧,Zed板上的Zynq是一个PS(processing sys ...

  2. svn 撤销 已提交的修改

    1.保证我们拿到的是最新代码:  svn update  假设最新版本号是28.  2.然后找出要回滚的确切版本号:  svn log [something]  假设根据svn log日志查出要回滚的 ...

  3. redhat防火墙管理

    systemctl status firewalldsystemctl stop firewalldsystemctl start firewalldsystemctl enable firewall ...

  4. Django - day00 第一个页面

    Django - day00 0.写在最前面 第一次接触Django,是在大三的做数据库课程设计的时候,当时好像还是1.8的版本,现转眼就到了2.0的版本. 当时由于没太多的课,仅花了不到一周的时间就 ...

  5. lintcode First Unique Number In Stream

    First Unique Number In Stream 描述: Given a continuous stream of numbers, write a function that return ...

  6. 数数字 (Digit Counting,ACM/ICPC Dannang 2007 ,UVa1225)

    题目描述:算法竞赛入门经典习题3-3 #include <stdio.h> #include <string.h> int main(int argc, char *argv[ ...

  7. Android开发-API指南-<path-permission>

    <path-permission> 英文原文:http://developer.android.com/guide/topics/manifest/path-permission-elem ...

  8. Python最长连续数列的O(n)解法

    题目 输入一个乱序的连续数列,输出其中最长连续数列长度,要求算法复杂度为 O(n) . 输入样例 100,4,200,1,3,2 54,55,300,12 1 5,4,3,2,1 1,2,3,4,5, ...

  9. DeepLearning - Forard & Backward Propogation

    In the previous post I go through basic 1-layer Neural Network with sigmoid activation function, inc ...

  10. Linux查看物理CPU个数,核数,逻辑CPU个数;内存信息

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cpuinfo| ...