@loj - 2250@ 「ZJOI2017」仙人掌
@题目描述@
如果一个无自环无重边无向连通图的任意一条边最多属于一个简单环,我们就称之为仙人掌。所谓简单环即不经过重复的结点的环。

现在九条可怜手上有一张无自环无重边的无向连通图,但是她觉得这张图中的边数太少了, 所以她想要在图上连上一些新的边。同时为了方便的存储这张无向图,图中的边数又不能太多。 经过权衡,她想要加边后得到的图为一棵仙人掌。
不难发现合法的加边方案有很多,可怜想要知道总共有多少不同的加边方案。
两个加边方案是不同的当且仅当一个方案中存在一条另一个方案中没有的边。
输入格式
多组数据,第一行输入一个整数 T 表示数据组数。
每组数据第一行输入两个整数 n, m,表示图中的点数与边数。
接下来 m 行,每行两个整数 u, v(1 <= u, v <= n, u ≠ v) 表示图中的一条边。
保证输入的图联通且没有自环与重边。
输出格式
对于每组数据,输出一个整数表示方案数,当然方案数可能很大,请对 998244353 取模后输出。
样例
样例输入
2
3 2
1 2
1 3
5 4
1 2
2 3
2 4
1 5
样例输出
2
8
数据范围与提示
1 <= ∑n <= 5*10^5,1 <= ∑m <= 10^6。
@solution@
如果所有简单环都没有公共边,则一个图是仙人掌。
我们跑一遍 tarjan,将所有返祖边对应的树链标记加一。最后如果有一条边标记 > 1 则不为仙人掌。
然后初始图肯定得是一棵仙人掌。显然我们不可能跨越环连边,于是可以把所有环上的边去掉。
剩下的图变成了一棵不相交的森林。森林之间不能连边,我们只能在树上连求方案数,再把所有树的方案数相乘。
怎么求一棵树连成仙人掌的方案数?一样要求所有简单环都没有公共边,则我们相当于选出若干条没有公共边的链,求方案数。
接下来?树形 dp?貌似没有什么高效的 dp 方法。
因为没有重边,所以我们选出来的链长度 > 1。我们再把问题进一步转化:将没有被选在链中去的那些边单独作一条链,则用边不相交的链覆盖树上所有边的方案唯一对应选出若干条没有公共边的链的方案。
接着考虑每个点的贡献,设点 i 的度数为 d[i]。则我们可以将 i 连出去的边两两配对(也可以不配对),表示 i 所相邻的配对的那些边在同一条链里。
记 f[i] 表示 i 条边互相匹配的方案数,则最终答案为 f[d[i]] 之积。
f[i] 很好求,有递推式 f[i] = f[i-1] + (i-1)*f[i-2]。前者表示不匹配,后者表示选一个匹配。
@accepted code@
#include<cstdio>
#define rep(G, x) for(Graph::edge *p = G.adj[x];p;p = p->nxt)
const int MAXN = 500000;
const int MAXM = 1000000;
const int MOD = 998244353;
struct Graph{
struct edge{
int to; edge *nxt;
}edges[2*MAXM + 5], *adj[MAXN + 5], *ecnt;
void clear(int n) {
ecnt = &edges[0];
for(int i=1;i<=n;i++)
adj[i] = NULL;
}
void addedge(int u, int v) {
edge *p = (++ecnt);
p->to = v, p->nxt = adj[u], adj[u] = p;
p = (++ecnt);
p->to = u, p->nxt = adj[v], adj[v] = p;
}
}G1, G2;
int f[MAXN + 5];
void init() {
f[0] = f[1] = 1;
for(int i=2;i<=MAXN;i++)
f[i] = (f[i - 1] + 1LL * (i - 1) * f[i - 2] % MOD) % MOD;
}
bool flag;
int d[MAXN + 5], s[MAXN + 5];
int dfn[MAXN + 5], dcnt;
void clear(int n) {
G1.clear(n), G2.clear(n);
for(int i=1;i<=n;i++)
d[i] = s[i] = dfn[i] = 0;
dcnt = 0, flag = true;
}
void tarjan(int x, int fa) {
dfn[x] = (++dcnt);
rep(G1, x) {
if( p->to == fa ) continue;
if( dfn[p->to] ) {
if( dfn[p->to] < dfn[x] )
s[x]++, s[p->to]--;
}
else tarjan(p->to, x), G2.addedge(x, p->to);
}
}
int dfs(int x, int fa) {
int ret = s[x];
rep(G2, x) {
if( p->to == fa ) continue;
int del = dfs(p->to, x);
ret += del;
if( del == 0 )
d[x]++, d[p->to]++;
else if( del >= 2 )
flag = false;
}
return ret;
}
void solve() {
int n, m; scanf("%d%d", &n, &m), clear(n);
for(int i=1;i<=m;i++) {
int u, v; scanf("%d%d", &u, &v);
G1.addedge(u, v);
}
tarjan(1, 0), dfs(1, 0);
if( flag ) {
int ans = 1;
for(int i=1;i<=n;i++)
ans = 1LL * ans * f[d[i]] % MOD;
printf("%d\n", ans);
}
else puts("0");
}
int main() {
init(); int T; scanf("%d", &T);
while( T-- ) solve();
}
@details@
坚定了我对于 ZJOI 的题都是不可做的题的决心。
@loj - 2250@ 「ZJOI2017」仙人掌的更多相关文章
- 「ZJOI2017」仙人掌
「ZJOI2017」仙人掌 题目大意: 给定一张无向联通图,求有多少种本质不同的不加重边的加边方案使得新图是个仙人掌. 解题思路: 如果原来的图不是仙人掌,那么答案就是 \(0\) ,否则求出这个仙人 ...
- Loj #2570. 「ZJOI2017」线段树
Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
随机推荐
- leyou_01_环境搭建
1.乐优商城项目搭建 前端技术: 基础的HTML.CSS.JavaScript(基于ES6标准) JQuery Vue.js 2.0以及基于Vue的框架:Vuetify 前端构建工具:WebPack ...
- linux系统之间互传文件
参考网址:http://blog.csdn.net/shaoxiaohu1/article/details/23191637 1.文件复制:本机->远程服务器: scp /home/shaoxi ...
- html中有序列表标签ol,li的高级应用
本文主要介绍html中有序列表标签ol,li的高级应用, 在网页设计时我们设计有序列表内容时,经常会在每个ITEM前手工加上一个数值,或是由程序加上这个数值. 而如果使用有序列表标签ol和li,则不需 ...
- 使用SpringBoot发送mail邮件
1.前言 发送邮件应该是网站的必备拓展功能之一,注册验证,忘记密码或者是给用户发送营销信息.正常我们会用JavaMail相关api来写发送邮件的相关代码,但现在springboot提供了一套更简易使用 ...
- vagrant简介
什么是vagrant? 简单理解,就是可以通过Vagrant这个工具管理虚拟机,比如说想创建一个centos环境的虚拟机,不需要安装系统这么麻烦,通过vagrant可以快速创建 官网地址:https: ...
- Faster RCNN算法demo代码解析
一. Faster-RCNN代码解释 先看看代码结构: Data: This directory holds (after you download them): Caffe models pre-t ...
- 通过pip工具安装selenium(初次安装、升级、降级)
1.初始安装 语法: install selenium==版本号 2.升级安装 3.降级安装 ----------------------------------------------------- ...
- iOS开发——你真的会用SDWebImage?
http://www.cocoachina.com/ios/20160503/16064.html 本文授权转载,作者:hosea_zhou(简书) SDWebImage作为目前最受欢迎的图片下载第三 ...
- SDUT-3378_数据结构实验之查找六:顺序查找
数据结构实验之查找六:顺序查找 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 在一个给定的无序序列里,查找与给定关键字 ...
- 【JZOJ4761】【NOIP2016提高A组模拟9.7】鼎纹
题目描述 输入 输出 样例输入 2 3 4 4 2 1100 0110 1100 10 01 10 00 2 2 2 2 11 11 01 10 样例输出 YES NO 数据范围 解法 由于鼎纹中的第 ...