题目

给定一个简单无向连通图,问有多少种加边方案使得这个图变成简单仙人掌。


分析

首先找到一棵生成树,考虑其它非树边所对应的树的路径上的边最多只能用一次,

这可以用树上差分做,如果一个点到其父节点的边被用了多次就一定无解。

否则没有被用过的部分将形成若干棵树,方案就是它们的乘积。

等于说问用若干条路径覆盖一棵树的方案。

设 \(dp[x]\) 表示以 \(x\) 为根的子树的方案数。

只需要考虑 \(x\) 的邻边如何连接,子树的答案直接相乘。

设 \(f[n]\) 表示 \(n\) 条边任意匹配的方案数,则

\(f[n]=f[n-2]*(n-1)+f[n-1]\)

那么 \(dp[x]*=f[deg[x]]\)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=500011,mod=998244353; struct node{int y,next;}e[N<<1],E[N<<1];
int f[N],c[N],v[N],as[N],hs[N],et=1,Et=1,n,dp[N],ans,fat[N],g[N],flag,upd,Lca[N<<1];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
inline void Clear(){
for (rr int i=1;i<=n;++i) c[i]=as[i]=hs[i]=0;
}
inline void dfs1(int x,int fa){
f[x]=x,v[x]=upd,fat[x]=fa;
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fa) dfs1(e[i].y,x),f[e[i].y]=x;
for (rr int i=hs[x];i;i=E[i].next)
if (v[E[i].y]==upd) Lca[i]=Lca[i^1]=getf(E[i].y);
}
inline void dfs2(int x,int fa){
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fa) dfs2(e[i].y,x),c[x]+=c[e[i].y];
}
inline void dfs3(int x,int TOP){
rr int sub=0; dp[x]=1;
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]){
if (!c[e[i].y]) dfs3(e[i].y,TOP),++sub,dp[x]=1ll*dp[x]*dp[e[i].y]%mod;
else dfs3(e[i].y,e[i].y);
}
if (x==TOP) ans=1ll*ans*dp[x]%mod*g[sub]%mod;
else dp[x]=1ll*dp[x]*g[sub+1]%mod;
}
signed main(){
g[0]=g[1]=1;
for (rr int i=2;i<N;++i) g[i]=(g[i-2]*(i-1ll)+g[i-1])%mod;
for (rr int T=iut();T;--T,putchar(10)){
n=iut(),et=Et=ans=flag=1,++upd;
for (rr int i=1;i<=n;++i) f[i]=i;
for (rr int TOT=iut();TOT;--TOT){
rr int x=iut(),y=iut();
if (getf(x)!=getf(y)){
rr int fa=getf(x),fb=getf(y);
if (fa>fb) fa^=fb,fb^=fa,fa^=fb;
f[fa]=fb;
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}else{
E[++Et]=(node){y,hs[x]},hs[x]=Et;
E[++Et]=(node){x,hs[y]},hs[y]=Et;
}
}
dfs1(1,0);
for (rr int i=2;i<=Et;i+=2)
++c[E[i].y],++c[E[i^1].y],c[Lca[i]]-=2;
dfs2(1,0);
for (rr int i=1;i<=n&&flag;++i)
if (c[i]>1) putchar(48),flag=0;
if (!flag) {Clear(); continue;}
dfs3(1,1),print(ans),Clear();
}
return 0;
}

#树形dp#洛谷 3687 [ZJOI2017]仙人掌的更多相关文章

  1. ●洛谷P3687 [ZJOI2017]仙人掌

    题链: https://www.luogu.org/problemnew/show/P3687题解: 计数DP,树形DP. (首先对于这个图来说,如果初始就不是仙人掌,那么就直接输出0) 然后由于本来 ...

  2. 树形DP 洛谷P2014 选课

    洛谷P2014 选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门 ...

  3. 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告

    P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...

  4. 洛谷P4244 [SHOI2008]仙人掌图 II

    传送门 首先不考虑带环的仙人掌,如果只是一棵普通的树,可以通过dp求每棵子树中的最长链和次长链求树的直径. 那么如果dfs的时候遇到了环,应该用环上的两点挂着的最长链加上两点间的距离来更新树的直径,并 ...

  5. 区间DP 洛谷P2858牛奶零食

    题目链接 题意:你有n个货物从1-n依次排列,每天可以从两侧选一个出来卖,卖的价格是当天的天数乘该货物的初始价格,问这批货物卖完的最大价格 输入:第一行n,之后是n个货物的初始价值 这道题不能用贪心做 ...

  6. P1279 字串距离 dp 洛谷

    题目描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X ...

  7. dp 洛谷P1977 出租车拼车 线性dp

    题目背景 话说小 x 有一次去参加比赛,虽然学校离比赛地点不太远,但小 x 还是想坐 出租车去.大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人 坐车去,还是一堆人一起,总共需要支付的钱 ...

  8. 经典DP 洛谷p1880 石子合并

    https://www.luogu.org/problemnew/show/P1880 题目 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新 ...

  9. [DP]洛谷P1115最大子段和

    题目来源 https://www.luogu.org/problemnew/show/P1115 题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 第一行是一 ...

  10. 尼克的任务 dp 洛谷1280

    蒟蒻表示老久没看过dp题目了,,挺水的一道dp题目都没想出来,,, 首先设dp[i]表示从开始到i时间的最大空闲时间,用vector to[x] 表示从x点开始的任务结束时间,cnt[x]表示从x开始 ...

随机推荐

  1. (微服务)服务治理:熔断器介绍以及hystrix-go的使用

    一.什么是熔断器 要理解熔断器,可以先看看电路中使用的保险丝. 保险丝(fuse)也被称为电流保险丝,IEC127 标准将它定义为"熔断体(fuse-link)".保险丝是一种保证 ...

  2. 硬件开发笔记(九): 硬件开发基本流程,制作一个USB转RS232的模块(八):创建asm1117-3.3V封装库并关联原理图元器件

    前言   有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的.为了更好的表述封装设计过程,本文描述了一个创建asm1117-3.3V封 ...

  3. 单表查询,多表查询,子查询---day37

    1.单表查询 # ### part1 单表查询 # sql 查询语句的完整语法 '''select..from..where..group by..having..order by..limit..' ...

  4. 关于Python中math 和 decimal 模块的解析与实践

    本文分享自华为云社区<Python数学模块深度解析与实战应用>,作者: 柠檬味拥抱. 在Python中,math 和 decimal 模块是处理数学运算的重要工具.math 提供了一系列常 ...

  5. vivo 在离线混部探索与实践

    作者:来自 vivo 互联网服务器团队 本文根据甘青.黄荣杰老师在"2023 vivo开发者大会"现场演讲内容整理而成. 伴随 vivo 互联网业务的高速发展,数据中心的规模不断扩 ...

  6. 在vue3中使用openlayers3实现track轨迹动画

    网上太多资料代码,抄来抄去,而且版本也是v5.x版本的,部分API已经弃用 基础知识不多说,直接讲重点 三个关键变量 // 记录开始动画的时间 const startTime = ref(0); // ...

  7. Spring事务(五)-事务隔离级别

    Spring @Transactional注解isolation属性 @Transactional注解通过isolation属性设置事务隔离级别.如下: @Transactional(isolatio ...

  8. vetur 和 volar 不要一起装 - vscode插件 已解决

    vetur 和 volar 不要一起装 - vscode插件 会有各种稀奇古怪的问题. 解决方案 利用 vscode 工作区 新建工作区 然后全局 将 volar 禁用工作区,起一个新的vue3项目, ...

  9. vue 打包 可以加 --watch 持续打包 - 开发本地应用程序 - 套壳模式开发

    vue 打包 可以加 --watch 持续打包 - 开发本地应用程序 - 套壳模式开发 "watch": "vue-cli-service build --watch - ...

  10. vue 下 placeholder 修改颜色

    input::placeholder{ color:#585c89 !important; }