Solution -「JSOI2008」「洛谷 P4208」最小生成树计数
\(\mathcal{Description}\)
link.
给定带权简单无向图,求其最小生成树个数。
顶点数 \(n\le10^2\),边数 \(m\le10^3\),相同边权的边数不超过 \(10\)。
\(\mathcal{Solution}\)
先说一个引理:对于一个图的任意两棵最小生成树,其边权集合相等。
简单证明一下,设有两个最小生成树的边权集合 \(\{\dots,a,b,\dots\},\{\dots,c,d,\cdots\}\)(省略号处相等,不降排列)。相当于第一棵最小棵树的 \(a,b\) 边替换为了 \(c,d\) 边形成第二棵。不妨设 \(c<a\le b<d\)。那么在第一棵树里先删去 \(a,b\) 边,此时图由三个联通块。加入 \(c\),显然 \(a,b\) 中的一条是能够再加入的。所以加入 \(d\) 不优,第二棵不是最小生成树,矛盾。
借此,先跑出一棵最小生成树,记为 \(T\),并得到每种边权的出现次数。枚举每种边权 \(w\),把在 \(T\) 中且边权不为 \(w\) 的边加入图,并加入边权为 \(w\) 的所有边。注意加入边权为 \(w\) 的边前需要缩点以保证不会漏选其余边。矩阵树求出此时生成树个数,最后乘法原理乘起来就得到答案了。复杂度 \(\mathcal O(n^3)\)。
\(\mathcal{Code}\)
#include <cstdio>
#include <algorithm>
#define fr first
#define sc second
const int MOD = 31011, MAXN = 100, MAXM = 1000;
int n, m, fa[MAXN + 5], col[MAXN + 5], K[MAXN + 5][MAXN + 5];
bool used[MAXM + 5];
std::pair<int, std::pair<int, int> > eset[MAXM + 5];
inline void init ( const int n ) { for ( int i = 1; i <= n; ++ i ) fa[i] = i; }
inline int find ( const int x ) { return x ^ fa[x] ? fa[x] = find ( fa[x] ) : x; }
inline bool unite ( const int a, const int b ) {
int u = find ( a ), v = find ( b );
return u ^ v ? fa[u] = v, true : false;
}
inline void add ( const int u, const int v ) {
++ K[u][u], ++ K[v][v], -- K[u][v], -- K[v][u];
if ( K[u][v] < 0 ) K[u][v] += MOD;
if ( K[v][u] < 0 ) K[v][u] += MOD;
}
inline int det ( const int n ) {
int ret = 1, swp = 1;
for ( int i = 1; i < n; ++ i ) {
for ( int j = i + 1; j < n; ++ j ) {
for ( ; K[j][i]; std::swap ( K[i], K[j] ), swp *= -1 ) {
int d = K[i][i] / K[j][i];
for ( int k = i; k < n; ++ k ) K[i][k] = ( K[i][k] - d * K[j][k] + MOD ) % MOD;
}
}
if ( ! ( ret = ret * K[i][i] % MOD ) ) return 0;
}
return ( ret * swp + MOD ) % MOD;
}
int main () {
scanf ( "%d %d", &n, &m );
for ( int i = 1, u, v, w; i <= m; ++ i ) {
scanf ( "%d %d %d", &u, &v, &w );
eset[i] = { w, { u, v } };
}
sort ( eset + 1, eset + m + 1 ), init ( n );
int cnt = 0;
for ( int i = 1; i <= m && cnt < n - 1; ++ i ) {
if ( unite ( eset[i].sc.fr, eset[i].sc.sc ) ) {
++ cnt, used[i] = true;
}
}
if ( cnt < n - 1 ) return puts ( "0" ), 0;
int ans = 1;
for ( int i = 1, j; i <= m; i = j + 1 ) {
init ( n );
for ( j = 1; j <= m; ++ j ) {
if ( used[j] && eset[i].fr ^ eset[j].fr ) {
unite ( eset[j].sc.fr, eset[j].sc.sc );
}
}
int blk = 0;
for ( j = 1; j <= n; ++ j ) if ( j == fa[j] ) col[j] = ++ blk;
for ( j = 1; j <= n; ++ j ) col[j] = col[find ( j )];
for ( j = 1; j <= blk; ++ j ) for ( int k = 1; k <= blk; ++ k ) K[j][k] = 0;
for ( j = i; j <= m; ++ j ) {
add ( col[eset[j].sc.fr], col[eset[j].sc.sc] );
if ( j == m || eset[j].fr ^ eset[j + 1].fr ) break;
}
ans = ans * det ( blk ) % MOD;
}
printf ( "%d\n", ans );
return 0;
}
Solution -「JSOI2008」「洛谷 P4208」最小生成树计数的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 洛谷 P1596 [USACO10OCT]湖计数Lake Counting
题目链接 https://www.luogu.org/problemnew/show/P1596 题目描述 Due to recent rains, water has pooled in vario ...
- 洛谷P1144 最短路计数(SPFA)
To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M ...
- 洛谷 1144 最短路计数 bfs
洛谷1144 最短路计数 传送门 其实这道题目的正解应该是spfa里面加一些处理,,然而,,然而,,既然它是无权图,,那么就直接bfs了,用一个cnt记录一下每一个点的方案数,分几种情况讨论一下转移, ...
- 洛谷 P4017 最大食物链计数
洛谷 P4017 最大食物链计数 洛谷传送门 题目背景 你知道食物链吗?Delia生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条.于是她来就来求助你,然而你也不会啊!写 ...
- 动态规划 洛谷P4017 最大食物链计数——图上动态规划 拓扑排序
洛谷P4017 最大食物链计数 这是洛谷一题普及/提高-的题目,也是我第一次做的一题 图上动态规划/拓扑排序 ,我认为这题是很好的学习拓扑排序的题目. 在这题中,我学到了几个名词,入度,出度,及没有环 ...
- Solution -「CTS 2019」「洛谷 P5404」氪金手游
\(\mathcal{Description}\) Link. 有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
随机推荐
- Bash 取字符串的最后 N 个字符 - ${str:0-N:LENGTH}
Bash 取字符串的最后 N 个字符: ${str:0-N:LENGTH} or ${str:0-N} https://tldp.org/LDP/abs/html/string-manipulatio ...
- alias 中使用 awk
alias hehistory10='history |awk "{print \$2}"|sort|uniq -c|sort -rn|head -10' alias lv='ls ...
- [ unittest ] 文档粗读
参考: https://blog.csdn.net/ljl6158999/article/details/80994979 1.概念提出 unittest最初灵感来自于Junit,它有着和其他单元测试 ...
- centos7 配置登录前和登录信息内容
登录之前提示信息: 登录之后提示信息: 上述中,只需修改对应的文件即可. 登录之前: vi /etc/issue 登录之后: vi /etc/motd 补充:将文件内容清空的方法,不是删除. 在前面文 ...
- GeoServer介绍
GeoServer本质上是一个地图服务器,它是遵循OpenGIS Web 服务器规范的J2EE实现,通过它可以方便的将地图数据发布为地图服务,实现地理空间数据在用户之间的共享.另外,它也提供了相应的接 ...
- python实现--九九乘法表
1 for i in range(1,10): 2 for j in range(1,i+1): 3 print("%d*%d=%d"%(j,i,j*i),end="\t ...
- 什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
1. XSS(Cross Site Script,跨站脚本攻击) 是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式. 1.1跨站脚本攻击分有两种形式: 反射型攻击(诱使用户点 ...
- http状态码 200 304 404 503等
浏览器采用http请求时,会封装http get等信息见下图请求头,然后服务器响应后回发一些信息,包括状态码,响应头,响应信息等等,如下图. 右上图可见两种状态码,一种是200 一种是304.其中20 ...
- MyCms 开源自媒体系统后台 角色管理&管理员管理操作说明
角色管理 功能说明 一.添加角色基本信息 填写角色名称.简要描述(一般以角色功能.职位等信息来命名) 二.角色授权 点击右侧的"授权"按钮,进行对角色授权,选择需要授权的功能模块后 ...
- golang中的切片
1. 切片中追加数据,如果没有扩容,内存地址不发生变化 // 1. 切片中追加数据,如果不扩容的话,内存地址不发生变化 v1 := make([]int, 1, 3) v2 := append(v1, ...