题目链接:BZOJ - 1016

题目分析

最小生成树的两个性质:

同一个图的最小生成树,满足:

1)同一种权值的边的个数相等

2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性相等

这样,先做一次Kruscal求出每种权值的边的条数,再按照权值从小到大,对每种边进行 DFS, 求出这种权值的边有几种选法。

最后根据乘法原理将各种边的选法数乘起来就可以了。

特别注意:在DFS中为了在向下DFS之后消除决策影响,恢复f[]数组之前的状态,在DFS中调用的Find()函数不能路径压缩。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm> using namespace std; const int MaxN = 100 + 5, MaxM = 1000 + 5, Mod = 31011; int n, m, Top, Sum, Cnt;
int f[MaxN], L[MaxM], R[MaxM], Num[MaxM]; typedef long long LL;
LL Ans; struct Edge
{
int u, v, w;
} E[MaxM]; inline bool Cmp(Edge e1, Edge e2)
{
return e1.w < e2.w;
} inline int Find(int x, int o)
{
int i, j, k;
j = x;
while (j != f[j]) j = f[j];
if (o == 1) return j;
i = x;
while (i != j)
{
k = i;
i = f[i];
f[k] = j;
}
return j;
} void DFS(int Type, int x, int y)
{
if (x == R[Type] + 1)
{
if (y == Num[Type]) ++Cnt;
return;
}
int fx, fy;
fx = Find(E[x].u, 1); fy = Find(E[x].v, 1);
if (fx != fy)
{
f[fx] = fy;
DFS(Type, x + 1, y + 1);
f[fx] = fx;
}
DFS(Type, x + 1, y);
} int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i)
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
sort(E + 1, E + m + 1, Cmp);
Top = 0; Sum = 0;
int fx, fy;
for (int i = 1; i <= n; ++i) f[i] = i;
for (int i = 1; i <= m; ++i)
{
if (i == 1 || E[i].w != E[i - 1].w) L[++Top] = i;
R[Top] = i;
fx = Find(E[i].u, 0); fy = Find(E[i].v, 0);
if (fx != fy)
{
f[fx] = fy;
++Num[Top];
++Sum;
}
}
if (Sum != n - 1)
{
printf("0\n");
return 0;
}
for (int i = 1; i <= n; ++i) f[i] = i;
Ans = 1;
for (int i = 1; i <= Top; ++i)
{
if (Num[i] == 0) continue;
Cnt = 0;
DFS(i, L[i], 0);
Ans = Ans * (LL)Cnt % Mod;
for (int j = L[i]; j <= R[i]; ++j)
{
fx = Find(E[j].u, 0); fy = Find(E[j].v, 0);
if (fx != fy) f[fx] = fy;
}
}
printf("%d\n", (int)Ans);
return 0;
}

  

[BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】的更多相关文章

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

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

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

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

  3. bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】

    有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...

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

    题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...

  5. bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...

  6. BZOJ 1016 [JSOI2008]最小生成树计数 ——Matrix-Tree定理

    考虑从小往大加边,然后把所有联通块的生成树个数计算出来. 然后把他们缩成一个点,继续添加下一组. 最后乘法原理即可. 写起来很恶心 #include <queue> #include &l ...

  7. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  8. 1016: [JSOI2008]最小生成树计数

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

  9. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

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

随机推荐

  1. 用tsung测试openfire 服务器性能

    最近公司需要做一个有聊天功能的应用,客户讲的是很宏大,用户超多,以前搞过openfire,但没有深入的去了解,就想用它来搞,而且是用 java写的,想扩展也容易些,但在性能上一直担忧,想测试一下它的性 ...

  2. careercup-数组和字符串1.8

    1.8 假定有一个方法isSubstring,可检查一个单词是否为其他字符串的子串.给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次isSubstring.旋转字符串: ...

  3. hdu2035java

    人见人爱A^B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  4. jackson 学习笔记

    Jackson以优异的解析性能赢得了好评,今天就看看Jackson的一些简单的用法. Jackson使用之前先要下载,这里一共有三个jar包,想要获得完美的Jackson体验,这三个jar包都不可或缺 ...

  5. Android开发之Action Bar

    Action Bar代替了传统的位于设备屏幕的标题栏,主要用来显示应用程序的图标和活动的名称以及添加定制动作项等功能. 1. 显示和隐藏Action Bar 显示和隐藏Action Bar 一般有两种 ...

  6. nodejs 中koa框架下的微信公众号开发初始篇

    最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂 ...

  7. linux lsof nmap netstat

    lsof -i :22    # 显示22端口当前运行的程序 lsof -c ssh  # 显示ssh进程打开的文件 lsof -p 2120  #显示进程id2120打开的文件   nmap -sP ...

  8. 免费的手机号码归属地查询API接口文档

    聚合数据手机号码归属四查询API接口,根据手机号码或手机号码的前7位,查询手机号码归属地信息,包括省份 .城市.区号.邮编.运营商和卡类型. 通过链接https://www.juhe.cn/docs/ ...

  9. window.resizeTo()和window.open()

    函数:window.resizeTo(width, height) 作用:改变窗口大小到设定的宽和高 参数:width - 宽度像素,必须设定的参数           height - 高度像素,可 ...

  10. 【转】怎样创建一个Xcode插件(Part 1)

      原文:How To Create an Xcode Plugin: Part 1/3 原作者:Derek Selander 译者:@yohunl 译者注:原文使用的是xcode6.3.2,我翻译的 ...