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]\) 内的元素排 ...
随机推荐
- Java 单引号 与 双引号 区别
双引号,用来引用字符串, 单引号用来表示单个字符.
- Vue-cli代理解决跨域问题
使用vue-cli调接口的时候,总是会出现垮与问题,因为vue的localhost与访问域名不一致导致.而这一点,开发者显然也想到了,故而在vuejs-templates,也就是vue-cli的使用的 ...
- Hive与MapReduce相关排序及自定义UDF函数
原文链接: https://www.toutiao.com/i6770870821809291788/ Hive和mapreduce相关的排序和运行的参数 1.设置每个reduce处理的数据量(单位是 ...
- 修正了Model1模式,进入如今盛行的的Model2模式,也就是MVC模式
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6513668601843548675/ 1.<JSP页面实际上就是Servlet> 2.<JSP页 ...
- Spring循环依赖原理
Spring循环依赖的原理解析 1.什么是循环依赖? 我们使用Spring的时候,在一个对象中注入另一个对象,但是另外的一个对象中也包含该对象.如图: 在Student中包含了teacher的一个 ...
- uboot无法通过nfs加载ubuntu18.04中的文件(转)
问题描述: i.mx6ull开发板,采用alientek官方维护的uboot,使用ubuntu18.04 lts作为nfs server,导致开发板uboot上nfs命令无法加载网络文件系统. 解决: ...
- 【原创】美团二面:聊聊你对 Kafka Consumer 的架构设计
在上一篇中我们详细聊了关于 Kafka Producer 内部的底层原理设计思想和细节, 本篇我们主要来聊聊 Kafka Consumer 即消费者的内部底层原理设计思想. 1.Consumer之总体 ...
- 【reverse】逆向5 标志寄存器
[reverse]逆向5 标志寄存器 1.引言 通过一个creak.exe文件的爆破,引出现阶段需要学习的知识 2.标志寄存器 标志寄存器有上图这么多个 记住这几个寄存器的位置和名称 下面是6个状态标 ...
- MacBookPro2021 M1-MAX电脑问题锦集
MacBook2021 M1-MAXPro电脑问题锦集 问题1: 开启硬盘加密,开机闪屏 问题详述: 在系统偏好设置中,打开安全与隐私,在弹出窗口中切换到第二个页签(文件保险箱),启用文件保险箱功能, ...
- golang中闭包讲解
1. 非闭包时的结果 package main import "fmt" func main() { var funcSlice []func() for i := 0; i &l ...