【学习笔记】广义串并联图方法
还是比较【小粉兔】的。
广义串并联图是指一类不存在同胚于
广义串并联图有几个性质:
,为平面图;- 通过若干次删
度点,缩 度点,叠合重边,最后一定会仅剩下一个点。
广义串并联图还有其它的一些性质,这里并不加以研究,相对来说最重要的性质为后一个性质。由于在很多问题中,将图删去一度点、缩二度点、叠合重边后的答案都是容易维护的,这使得广义串并联图相关的问题有了很简单的解决方法。
但是实际问题中给出的是广义串并联图的情况并不多,但是其使用的删
具体来讲,存在一类问题,满足有
实现上,我们可以拿 map
维护所有的边,拿队列维护所有度数
具体应用拿例题来看:
不知道哪来的据说是经典题的题
求给
首先当
这个可以子集卷积
然后考虑如何将一个图缩为上述限制的图。我们对于每一条边,设两个值
- 删一度点:那么我们可以直接将
统计到总答案上,并把这个点删去; - 缩二度点:
,两条边必须同向; ,要不然都不连通,要不然两个有一个不连通,要不然两个都连通但是方向相反;
- 叠合重边:
,要不然其中一条是不连通的,靠另一条边连通,要不然两条边同向; ,只有两条边都不连通才可能不连通。
那么最后计算答案的时候,每条边有三种情况,定一个向或断开。为了方便计算,我们先将
SNOI2020 生成树
求一个仙人掌图上加一条边的图的生成树个数。
可以发现,这张图是广义串并联图,那么也就是说最后可以缩成一个点。
那么仍然考虑上述做法,设
- 删一度点:那么这条边一定是要选的,把
乘到答案上; - 缩二度点:
; ,没有 的原因是中间的点必须得和左右两个点其中一个连通。
- 叠合重边:
; 。
直接做即可。
code#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500005, P = 998244353;
int n, m;
map<int, pair<int, int>> e[MAXN];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v; scanf("%d%d", &u, &v);
e[u][v] = e[v][u] = { e[u][v].first + 1, 1 };
}
queue<int> q;
for (int i = 1; i <= n; i++) if (e[i].size() <= 2) q.push(i);
int ans = 1;
while (!q.empty()) {
int u = q.front(); q.pop();
if (e[u].size() == 0) continue;
for (auto p : e[u]) e[p.first].erase(u);
if (e[u].size() == 1) {
auto [f, g] = e[u].begin()->second;
ans = 1ll * ans * f % P;
} else {
auto [f1, g1] = e[u].begin()->second;
auto [f2, g2] = next(e[u].begin())->second;
int f = 1ll * f1 * f2 % P, g = (1ll * f1 * g2 + 1ll * f2 * g1) % P;
int x = e[u].begin()->first, y = next(e[u].begin())->first;
if (e[x].count(y)) {
auto [f3, g3] = e[x][y];
e[x][y] = e[y][x] = {
(1ll * f * g3 + 1ll * g * f3) % P,
1ll * g * g3 % P
};
} else e[x][y] = e[y][x] = { f, g };
}
for (auto p : e[u]) if (e[p.first].size() <= 2) q.push(p.first);
e[u].clear();
}
printf("%d\n", ans);
return 0;
}
P8426 [JOI Open 2022] 放学路(School Road)
给定一张图,求
这个从部分分一步一步分析。
发现
首先我们肯定只需要找出
这就是本文所说到的方法了,考虑直接删一度点缩二度点叠合重边,那么最后的
具体来讲,删一度点直接删就行,叠合重边的时候如果两条边的长度不相等,那么就将这条边的边权设为
图为点双连通分量
注意到如果上述算法最后仅剩下一条边且不为
虽然这个结论并不在一般图上成立,但是可以证明它在点双上是成立的。或者由于它给出了点双的部分分,你猜测它在点双上是成立的。
考虑如果最后剩下若干个点,那么这些点除了
我们首先给这张图定向,方向为最短路的方向,即
如果一个点入度小于出度,我们称其为红点,否则称其为蓝点。
考虑
那么在这条路径上,一定存在一条边
那么我们只需要跑上述算法就能很轻松的判定答案了。
正解
实际上正解就很简单了,
「2019 集训队互测 Day 3」公园
对每条边维护
带修需要把这个过程记录下来然后用矩阵表示,跑动态 DP。
我不想碰,告辞。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧