题目描述

如果一个无自环无重边无向连通图的任意一条边最多属于一个简单环,我们就称之为仙人掌。所谓简单环即不经过
重复的结点的环。
现在九条可怜手上有一张无自环无重边的无向连通图,但是她觉得这张图中的边数太少了,所以她想要在图上连上
一些新的边。同时为了方便的存储这张无向图,图中的边数又不能太多。经过权衡,她想要加边后得到的图为一棵
仙人掌。不难发现合法的加边方案有很多,可怜想要知道总共有多少不同的加边方案。两个加边方案是不同的当且
仅当一个方案中存在一条另一个方案中没有的边。

输入格式

多组数据,第一行输入一个整数T表示数据组数。
每组数据第一行输入两个整数n,m,表示图中的点数与边数。
接下来m行,每行两个整数u,v(1≤u,v≤n,u!=v)表示图中的一条边。保证输入的图
联通且没有自环与重边
Sigma(n)<=5*10^5,m<=10^6,1<=m<=n*(n-1)/2

输出格式

对于每组数据,输出一个整数表示方案数,当然方案数可能很大,请对998244353取模后
输出。

  • 题解:

    • 由于环上的边无法再被另外的环覆盖,所以把所有的环拆掉得到森林;
    • 计算每颗树的$ans$乘起来;
    • $f[u]$表示以$u$为根的子树的方案,$g[u]$表示以$u$为根的子树并且还有某个点可以向上连边的方案;
    • 由于根也可以向上连,$g[u]$是包含$f[u]$的;
    • $f[u]$的递推可以将所有的儿子$v$的$g[v]$乘起来,在乘以儿子之间的互相连边或和$u$连边的方案数;
    • $h[i]$表示$i$个儿子时互相连边的方案:
    • $h[i] = h[i-1] + h[i-2]*(i-1)$;
    • $tot$表示$u$的儿子的个数:
    • $f[u] = \Pi_{v}g[v] * h[tot]$;
    • $u$的子树向上连边可以由$u$或者$u$的一个儿子$v$的子树向上连边;
    • $g[u] = f[u] + tot * \Pi_{v}g[v] h[tot-1] = \Pi_{v}g[v]*h[tot+1]$;
    • 我一直在纠结不连边的方案去哪了?其实不连边的方案数在统计$v$向上连到$u$时被统计了;
  •  #include<bits/stdc++.h>
    using namespace std;
    const int N=,mod=;
    char gc(){
    static char*p1,*p2,s[];
    if(p1==p2)p2=(p1=s)+fread(s,,,stdin);
    return(p1==p2)?EOF:*p1++;
    }
    int rd(){
    int x=;char c=gc();
    while(c<''||c>'')c=gc();
    while(c>=''&&c<='')x=(x<<)+(x<<)+c-'',c=gc();
    return x;
    }
    int T,n,m,vis[N],bl[N],dfn[N],low[N],idx,fg,ans,st[N],top,o,hd[N],cnt,f[N],g[N],h[N],d[N];
    struct Edge{int v,nt;}E[N<<];
    inline void adde(int u,int v){
    E[o]=(Edge){v,hd[u]};hd[u]=o++;
    E[o]=(Edge){u,hd[v]};hd[v]=o++;
    }
    void tarjan(int u,int fa){
    if(fg)return;
    dfn[st[++top]=u]=low[u]=++idx;
    int tot=;
    for(int i=hd[u],v;i;i=E[i].nt){
    v=E[i].v;
    if(v==fa)continue;
    if(dfn[v=E[i].v]){
    if(d[v])continue;
    if(dfn[v]<dfn[u]&&tot++){fg=;break;}
    low[u]=min(low[u],dfn[v]);
    }else{
    tarjan(v,u);
    if(low[v]<dfn[u]&&tot++){fg=;break;}
    low[u]=min(low[u],low[v]);
    }
    }
    if(dfn[u]==low[u]){
    int v;++cnt;
    do{bl[v=st[top--]]=cnt;d[v]=;}while(v!=u);
    }
    }
    void dfs(int u){
    f[u]=g[u]=vis[u]=;
    int tot=;
    for(int i=hd[u];i;i=E[i].nt){
    int v=E[i].v;
    if(vis[v]||bl[v]==bl[u])continue;
    tot++;
    dfs(v);
    f[u]=1ll*f[u]*g[v]%mod;
    g[u]=1ll*g[u]*g[v]%mod;
    }
    f[u]=1ll*f[u]*h[tot]%mod;
    g[u]=1ll*g[u]*h[tot+]%mod;
    }
    int main(){
    #ifndef ONLINE_JUDGE
    freopen("T1.in","r",stdin);
    freopen("T1.out","w",stdout);
    #endif
    T=rd();
    h[]=h[]=;
    for(int i=;i<=;++i)h[i]=(h[i-]+1ll*(i-)*h[i-]%mod)%mod;
    while(T--){
    n=rd();m=rd();
    fg=idx=cnt=top=;ans=o=;
    for(int i=;i<=n;++i)vis[i]=hd[i]=dfn[i]=d[i]=low[i]=;
    for(int i=;i<=m;++i)adde(rd(),rd());
    tarjan(,);
    if(fg){puts("");continue;}
    for(int i=;i<=n;++i)if(!vis[i]){
    dfs(i);
    ans = 1ll * ans * f[i]%mod;
    }
    printf("%d\n",ans);
    }
    return ;
    }

    bzoj4784

bzoj4784【zjoi2017】仙人掌的更多相关文章

  1. [BZOJ4784][ZJOI2017]仙人掌(树形DP)

    4784: [Zjoi2017]仙人掌 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 312  Solved: 181[Submit][Status] ...

  2. BZOJ4784 ZJOI2017仙人掌(树形dp+dfs树)

    首先考虑是棵树的话怎么做.可以发现相当于在树上选择一些长度>=2的路径使其没有交,同时也就相当于用一些没有交的路径覆盖整棵树. 那么设f[i]为覆盖i子树的方案数.转移时考虑包含根的路径.注意到 ...

  3. bzoj4784 [Zjoi2017]仙人掌

    Description 如果一个无自环无重边无向连通图的任意一条边最多属于一个简单环,我们就称之为仙人掌.所谓简单环即不经过重复的结点的环. 现在九条可怜手上有一张无自环无重边的无向连通图,但是她觉得 ...

  4. 2019.02.07 bzoj4784: [Zjoi2017]仙人掌(仙人掌+树形dp)

    传送门 题意:给一个无向连通图,问给它加边形成仙人掌的方案数. 思路: 先考虑给一棵树加边形成仙人掌的方案数. 这个显然可以做树形dp. fif_ifi​表示把iii为根的子树加边形成仙人掌的方案数. ...

  5. 【BZOJ4784】[ZJOI2017]仙人掌(Tarjan,动态规划)

    [BZOJ4784][ZJOI2017]仙人掌(Tarjan,动态规划) 题面 BZOJ 洛谷 题解 显然如果原图不是仙人掌就无解. 如果原图是仙人掌,显然就是把环上的边给去掉,变成若干森林连边成为仙 ...

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

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

  7. 【做题】ZJOI2017仙人掌——组合计数

    原文链接 https://www.cnblogs.com/cly-none/p/ZJOI2017cactus.html 给出一个\(n\)个点\(m\)条边的无向连通图,求有多少种加边方案,使得加完后 ...

  8. LOJ2250 [ZJOI2017] 仙人掌【树形DP】【DFS树】

    题目分析: 不难注意到仙人掌边可以删掉.在森林中考虑树形DP. 题目中说边不能重复,但我们可以在结束后没覆盖的边覆盖一个重复边,不改变方案数. 接着将所有的边接到当前点,然后每两个方案可以任意拼接.然 ...

  9. zjoi2017 仙人掌

    题解: 好难的dp啊...看题解看了好久才看懂 http://blog.csdn.net/akak__ii/article/details/65935711 如果一开始的图就不是仙人掌,答案显然为0, ...

  10. 【题解】ZJOI2017仙人掌

    感觉这题很厉害啊,虽然想了一天多但还是失败了……(:д:) 这题首先注意到给定图中如果存在环其实对于答案是没有影响的.然后关键之处就在于两个 \(dp\) 数组,其中 \(f[u]\) 表示以 \(u ...

随机推荐

  1. 王者荣耀交流协会final发布第五次scrum例会

    1.例会照片 成员高远博,冉华,王磊,王玉玲,任思佳,袁玥,王磊,王超. master:王磊 2.时间跨度 2017年12月5日 18:00 — 18:21,总计21分钟 3.地点 一食堂二楼沙发座椅 ...

  2. Scrum Meeting 10.27

    1.会议内容: 姓名 今日任务 明日任务 预估时间(h) 徐越 配置SQLserver 学习本地和服务器之间的通信 4 卞忠昊 找上届代码的bug 学习安卓布局(layout)的有关知识,研究上届学长 ...

  3. "重力锁屏"Beta版使用说明

    一.产品介绍 重力锁屏是基于android系统的一款锁屏软件.它利用重力感应器来判断用户的动作从而自动锁屏亮屏,是锁屏软件的一大创新.相比传统的锁屏软件,“重力锁屏”从可操作性.方便性.功能全面性都有 ...

  4. 图文转换NABCD

    作为图文转化还是有很多优点的,在这里我就分析一下它的方便快捷 Need:有些非电子版的文字不方便我们编辑,图文转换可以轻而易举达到目的. Approach:现在技术手段应该还有点难度,应该可以换个方法 ...

  5. 《Spring2之站立会议8》

    <Spring2之站立会议8> 昨天,添加了登录界面: 今天,准备添加注册界面: 遇到的问题:过程中遇到了一些困难,不过还是解决了.

  6. 在ASP.NET里实现计算器代码的封装

    一.具体代码 Default2.aspx.cs public partial class Chapter1_Default2 : System.Web.UI.Page { protected void ...

  7. java的小学生四则运算

    import java.awt.*; import java.awt.event.*; import java.io.FileNotFoundException; import java.io.IOE ...

  8. Internet History, Technology and Security (Week3)

    Week3. Welcome to week 3! This is our fourth and final week of History where we make the connection ...

  9. 牛客网国庆集训派对Day3题目 2018年

    链接:https://www.nowcoder.com/acm/contest/203/D来源:牛客网 Shopping 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K ...

  10. Linux操作系统(一)

    操作系统:介于硬件与用户之间的一组程序,方便用户操作,用以管理计算机的所有活动及硬件资源. 1.硬件->内核->系统调用(shell.命令)->应用程序. 只要具备以下几点,即可称为 ...