P2143 [JSOI2010] 巨额奖金 题解

news/发布时间2024/5/9 2:11:38

P2143 [JSOI2010] 巨额奖金 题解

矩阵树定理+Kruskal

最小生成树计数。

思路

MST 都是喵喵题。

引理 1:所有合法的权值相同边的连边方案,得到的连通块情况是相同的。

感性理解:如果不相同意味着至少有一条边可以连通一对连通块。

所以我们可以这么做:先跑 Kruskal 标记树边,然后枚举边权,对于同一边权的树边先删掉,所有剩余的图用并查集缩点,之后加入当前边权的边,缩点后图的生成树个数就是当前边权边的放置方案,根据引理,每个边权贡献独立,所以乘法原理即可。

注意每次要把所有的非当前边权的树边加入,否则可能导致图不连通。

时间复杂度:\(O(n^3)\)

// Problem: P4208 [JSOI2008] 最小生成树计数
// Author: Moyou
// Copyright (c) 2024 Moyou All rights reserved.
// Date: 2024-04-02 13:29:52#include <algorithm>
#include <iostream>
#include <map>
#define int long long
using namespace std;
const int N = 200 + 10, mod = 31011;int n, m, lap[N][N], fa[N];
struct qwq {int u, v, w;
} e[1010];
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
void merge(int a, int b) {int x = find(a), y = find(b);if(x == y) return ;fa[x] = y;
}
int tot;
map<int, int> h;
int id(int x) {if(h.count(x)) return h[x];return h[x] = ++ tot;
}
void add(int a, int b) {lap[a][a] ++, lap[b][b] ++, lap[a][b] --, lap[b][a] --;
}
int det(int n) {int c = 1;for(int i = 1; i < n; i ++)for(int j = i + 1; j < n; j ++)while(lap[j][i]) {int d = lap[i][i] / lap[j][i];for(int k = i; k < n && d; k ++)lap[i][k] = (lap[i][k] - 1ll * d * lap[j][k] % mod) % mod;swap(lap[i], lap[j]), c = -c;}for(int i = 1; i < n; i ++) c = 1ll * c * lap[i][i] % mod;return (c + mod) % mod;
}
void clear() {for(int i = 1; i <= tot; i ++)for(int j = 1; j <= tot; j ++)lap[i][j] = 0;tot = 0; h.clear();
}
bool ok[1010];
void kruskal() {for(int i = 1; i <= n; i ++) fa[i] = i;for(int i = 1; i <= m; i ++) {int x = find(e[i].u), y = find(e[i].v);if(x != y) fa[x] = y, ok[i] = 1;}
}signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin >> n >> m;for(int i = 1; i <= m; i ++)cin >> e[i].u >> e[i].v >> e[i].w;sort(e + 1, e + m + 1, [](qwq a, qwq b) {return a.w < b.w;});int ans = 1;kruskal();for(int i = 1, j = 0; i <= m; i = j + 1) {clear();for(int i = 1; i <= n; i ++) fa[i] = i;j = i;while(j < m && e[j + 1].w == e[i].w) j ++;for(int k = 1; k < i; k ++) if(ok[k]) merge(e[k].u, e[k].v);for(int k = j + 1; k <= m; k ++) if(ok[k]) merge(e[k].u, e[k].v);for(int k = i; k <= j; k ++) {int x = find(e[k].u), y = find(e[k].v);if(x != y) add(id(x), id(y));}for(int k = i; k <= j; k ++)merge(e[k].u, e[k].v);ans = 1ll * ans * det(tot) % mod;}for(int i = 1; i < n; i ++) if(find(i) != find(i + 1)) return cout << 0, 0;cout << ans << '\n';return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/82787882.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

MAT确认导致OOM的具体功能表单的过程

MAT发现导致OOM的具体功能表单的过程背景 愚人节这一天公司项目出现了 大量FullGC的情况. 群里发出来之后这边进行了一些简单的问题查找.堆区设置的事 30G 然后 dump文件是 35G左右. 下载和解压缩耗时 15min 使用40G堆区 全闪的Window虚拟机进行解析 耗时 30分钟.最近自己眼神不…

DC电源模块的市场发展趋势分析

BOSHIDA DC电源模块的市场发展趋势分析 DC电源模块是一种将交流电转换为直流电的模块,广泛应用于各种电子设备中。随着科技的不断发展和电子产品的普及,DC电源模块市场也在不断扩大。本文将对DC电源模块的市场发展趋势进行分析。 第一,随着电子产品的不断更新换代,对于电源…

MySQL事务隔离级别

简单来说,事务就是要保证一组数据库操作,要不全部成功,要不全部失败,在 MySQL 中,事务支持是在存储引擎层面的,比如 MySQL 的原生 MyISAM 存储引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因。 一、隔离性 事务的隔离性,就是我们常说的 ICAD(Atomicity,Co…

去除电脑的管理员密码、安装金格浏览器

问题:忘记笔忘本电脑管理员的密码 思路:制作PE系统的U盘启动盘,设置BIOS从U盘启动,进入后重置管理员的密码为空后。重启电脑即可 第一步:下载制作启动用U盘的工具 https://www.bilibili.com/video/BV1qk4y1c7AH/?spm_id_from=333.337.search-card.all.click&vd…

三极管是()控制元件,MOS是()控制元件。

答案: 电流 电压解析:MOS管属于电压控制元件(维持GS之间的电压差即可导通) 三极管属于电流控制元件(BE之间需要存在持续的电流才能导通)

vue 子父窗体

一、子父组件传值 比较全:https://blog.csdn.net/libusi001/article/details/131668644 1.Props 子窗口修改父窗口传的值。props 见如下,一种可以,另一种不可以,版本vue32.$refs属性 父组件可以通过$refs获取子组件的实例,进而访问子组件的属性和方法。 父:<el-tab-pa…