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

摘自大佬博客:

https://blog.sengxian.com/solutions/bzoj-1016

http://www.cnblogs.com/Y-E-T-I/p/8462255.html#undefined

https://kelin.blog.luogu.org/solution-p4208

https://cnyali-lk.blog.luogu.org/solution-p4208

#include <bits/stdc++.h>
#define fp(i, a, b) for (register int i = a, I = b + 1; i < I; ++i)
#define fd(i, a, b) for (register int i = a, I = b - 1; i > I; --i)
#define go(u) for (register int i = fi[u], v = e[i].to; i; v = e[i = e[i].nx].to)
#define file(s) freopen(s ".in", "r", stdin), freopen(s ".out", "w", stdout)
template <class T>
inline bool cmax(T &a, const T &b) { return a < b ? a = b, : ; }
template <class T>
inline bool cmin(T &a, const T &b) { return a > b ? a = b, : ; }
using namespace std;
const int N = , M = , P = ;
typedef int arr[N];
struct eg
{
int u, v, w;
} e[M];
int n, m, ans = ;
arr fa, bl, vis, g[N], G[N];
vector<int> s[N];
int gf(int u, int *fa) { return fa[u] == u ? u : fa[u] = gf(fa[u], fa); }//find并查集
inline int pls(int a, int b) { return a += b, a >= P ? a - P : a; }//模数不为质数的操作
inline int sub(int a, int b) { return a -= b, a < ? a + P : a; }
inline int det(int n)//返回缩点的生成树个数
{
int a, b, t, f = , tp = ;
fp(i, , n) fp(j, , n) G[i][j] = pls(P, G[i][j]);
fp(i, , n)
{
fp(j, i + , n)
{
a = G[i][i], b = G[j][i];
while (b)
{
t = a / b;
a %= b;
swap(a, b);
fp(k, i, n) G[i][k] = sub(G[i][k], t * G[j][k] % P);
fp(k, i, n) swap(G[i][k], G[j][k]);
f = -f;
}
}
if (!G[i][i])
return ;
tp = tp * G[i][i] % P;
}
return pls(P, f * tp);
}
inline void calc()//合并联通块形成缩点
{
fp(i, , n) if (vis[i])
{
s[gf(i, fa)].push_back(i);
vis[i] = ;
}
fp(i, , n) if (s[i].size() > )
{
int t = s[i].size(), *a = s[i].data();
memset(G, , sizeof G);
fp(j, , t) fp(k, j + , t)
{
int u = a[j - ], v = a[k - ];
if (g[u][v])
{
G[j][k] = G[k][j] = -g[u][v];
G[j][j] += g[u][v], G[k][k] += g[u][v];
}
}
ans = ans * det(t - ) % P;
fp(j, , t) bl[a[j - ]] = i;//属于同一联通块
}
fp(i, , n) s[i].clear(), fa[i] = bl[i] = gf(i, bl);
}
inline bool cmp(const eg &a, const eg &b) { return a.w < b.w; }
int main()
{
#ifndef ONLINE_JUDGE
file("s");
#endif
scanf("%d%d", &n, &m);
fp(i, , n) fa[i] = bl[i] = i;
fp(i, , m) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
sort(e + , e + m + , cmp);
e[] = e[];
fp(i, , m)
{
//发现不相同的边界点就计算处理
if (e[i].w ^ e[i - ].w)
calc();
//同一权值合并
int u = gf(e[i].u, bl), v = gf(e[i].v, bl);
if (u ^ v)
{
vis[u] = vis[v] = ;
++g[u][v], ++g[v][u];
fa[gf(u, fa)] = gf(v, fa);
}
}
calc();
fp(i, , n) if (bl[i] ^ bl[i - ]) return puts(""), ;
printf("%d", ans);
return ;
}

P4208 [JSOI2008]最小生成树计数的更多相关文章

  1. [洛谷P4208][JSOI2008]最小生成树计数

    题目大意:有$n$个点和$m$条边(最多有$10$条边边权相同),求最小生成树个数 题解:对于所有最小生成树,每种边权的边数是一样的.于是就可以求出每种边权在最小生成树中的个数,枚举这种边的边集,求出 ...

  2. 洛谷P4208 [JSOI2008]最小生成树计数——题解

    题目传送 前置知识:对于同一个图的所有最小生成树,权值相等的边的数量相同. 可以简单证明一下: 我们可以从kruskal的过程考虑.这个算法把所有边按权值大小从小到大排序,然后按顺序看每条边,只要加上 ...

  3. Luogu P4208 [JSOI2008]最小生成树计数

    题意 给定一个 \(n\) 个点 \(m\) 条边的图,求最小生成树的个数. \(\texttt{Data Range:}1\leq n\leq 100,1\leq m\leq 10^4\) 题解 一 ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. jquery之行自加自减

    实现目标:点击按钮复制本行,修改后重新插入到本行后面,点击复制出的行可删除本行 代码如下: <!DOCTYPE html> <html lang="en"> ...

  2. 基于InfluxDB实现分页查询功能

    InfluxDB作为时序数据库中的翘楚,应用范围非常广泛,尤其在监控领域. 最近做了一个功能,将InfluxDB中的数据查询出来后,在前台分页展现,比如每页10条,一共100页,可以查看首页.末页,进 ...

  3. getWidth()和getMeasuredWidth()的区别

    结论:getMeasuredWidth()获取的是view原始的大小,也就是这个view在XML文件中配置或者是代码中设置的大小.getWidth()获取的是这个view最终显示的大小,这个大小有可能 ...

  4. Luncene介绍

    1.Luncene介绍 案例:实现一个文件的搜索功能,通过关键字搜索文件,凡是文件名或文件内容包括关键字文件都需要找出来.还可以根据中文词语进行查询,并且需要支持多个条件查询.Lucene可以解决 数 ...

  5. win10下解压版mysql-8.0.12安装教程

    内容转载于:https://blog.csdn.net/hust_hqq/article/details/80572133 在他之上添加了一个:服务名无效的解决方法 1.官网下载安装包 网址:http ...

  6. 深度学习word embedding猜测性别初探

    根据用户的一些特征数据,如果能推测出用户的性别借此提高产品的服务质量.广告的精准性等都是极好的. 机器学习方法有很多,而且一般都可以达到不错的效果,比如svm或神经网络等. 本文使用的代码参考——&l ...

  7. 【PAT】B1076 Wifi密码(15 分)

    注意接收字符时缓冲区的换行要接受掉 #include<stdio.h> int main() { int n; scanf("%d", &n); n *= 4; ...

  8. logstash过滤器插件filter详解及实例

    1.logstash过滤器插件filter 1.1.grok正则捕获 grok是一个十分强大的logstash filter插件,他可以通过正则解析任意文本,将非结构化日志数据弄成结构化和方便查询的结 ...

  9. 第3章 Git使用人门

    [初识Github] 首先让我们大家一起喊一句“Hello Github”.YEAH!就是这样. Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理 ...

  10. 个人技术博客--团队Git规范(参考西瓜学长)

    援引西瓜学长:GitHub团队项目合作流程 废话少说直接写 1.fork 1.对于组员来说第一步就是fork 2.点击fork之后 上面是我们的团队仓库 切换回自己的仓库 就会看到 是fork于团队仓 ...