P4208 [JSOI2008]最小生成树计数
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)输出方案数对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]最小生成树计数的更多相关文章
- [洛谷P4208][JSOI2008]最小生成树计数
题目大意:有$n$个点和$m$条边(最多有$10$条边边权相同),求最小生成树个数 题解:对于所有最小生成树,每种边权的边数是一样的.于是就可以求出每种边权在最小生成树中的个数,枚举这种边的边集,求出 ...
- 洛谷P4208 [JSOI2008]最小生成树计数——题解
题目传送 前置知识:对于同一个图的所有最小生成树,权值相等的边的数量相同. 可以简单证明一下: 我们可以从kruskal的过程考虑.这个算法把所有边按权值大小从小到大排序,然后按顺序看每条边,只要加上 ...
- Luogu P4208 [JSOI2008]最小生成树计数
题意 给定一个 \(n\) 个点 \(m\) 条边的图,求最小生成树的个数. \(\texttt{Data Range:}1\leq n\leq 100,1\leq m\leq 10^4\) 题解 一 ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3517 Solved: 1396[Submit][St ...
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
- 1016: [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6200 Solved: 2518[Submit][St ...
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...
- 【bzoj1016】[JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4863 Solved: 1973[Submit][St ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
随机推荐
- bootstrap网站后台从设计到开发之登录
节后综合征缓了两天,今天把登录界面的主要后台代码分享给大家. protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPo ...
- mock数据的基础使用
一.应用场景 在我们自己做一个项目时,会遇到后端还没完成数据输出或者接口没写好的情况.你没有办法想后台获取数据,这时候需要前端只好自己写静态模拟数据(假数据).mockjs就是用来创造假数据的,他的用 ...
- 为什么radio没有出现单选效果?
原因是radio一定要设置相同的name,如下: <input type="radio" name="yunsuan" checked="che ...
- Salesforce自定义权限简介
自定义权限(Custom Permission) Salesforce默认提供了多种方式设定用户的权限,比如简档.权限集等.在这些设定中,已经包括了系统中的对象.应用.字段.页面布局等组件,管理员或开 ...
- CloudSim源代码学习——虚拟机(VM)
package org.cloudbus.cloudsim; import java.util.ArrayList;//This class provides methods to manipulat ...
- Kotlin入门(8)空值的判断与处理
上一篇文章介绍了如何对循环语句进行操作,末尾还演示了发现空串时直接继续下一循环,只是在初始化字符串数组时使用了“val poem2Array:Array<String?> = ***”,该 ...
- python的subprocess模块执行shell命令
subprocess模块可以允许我们执行shell命令 一般来说,使用run()方法就可以满足大部分情况 使用run执行shell命令 In [5]: subprocess.run('echo &qu ...
- [20180327]行迁移与ITL浪费.txt
[20180327]行迁移与ITL浪费.txt --//生产系统遇到的一个问题,增加一个字段到表结构,修改数据字典,导致出现行迁移,而更加严重的是没有修改pctfree值,--//以后的业务操作,依旧 ...
- input子系统事件处理层(evdev)的环形缓冲区【转】
在事件处理层(evdev.c)中结构体evdev_client定义了一个环形缓冲区(circular buffer),其原理是用数组的方式实现了一个先进先出的循环队列(circular queue), ...
- 代理ARP--善意的欺骗
1. 代理ARP(Proxy ARP)是什么? 顾名思义,它指通过中间设备(通常为Router)代替其他主机响应ARP请求.对于没有配置默认网关的主机想要与其他网络的另一台主机通信时,网关收到源主机的 ...