题目描述

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

输入格式

多组数据,第一行输入一个整数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. 下一代的DevOps服务:AIOps

    AIOps是一个总称,用于指代使用复杂的基础设施管理软件和云解决方案监控工具来实现自动化数据分析和日常的DevOps操作. 那些10年前甚至是5年前构建的系统监控工具的主要缺陷是它们不是为了满足大数据 ...

  2. 琴声不等式--jensen

    (来自百度百科) 1. 凹函数,不加权 2. 凹函数,加权 3. 凸函数,不加权 4. 凸函数,加权 应用 在EM算法Q函数的推导中,用到了第二个不等式(凹函数,加权)

  3. 2019 年软件开发人员必学的编程语言 Top 3

    AI 前线导读:这篇文章将探讨编程语言世界的现在和未来,这些语言让新一代软件开发者成为这个数字世界的关键参与者,他们让这个世界变得更健壮.连接更加紧密和更有意义.开发者要想在 2019 年脱颖而出,这 ...

  4. 【推荐系统】neural_collaborative_filtering(源码解析)

    很久没看推荐系统相关的论文了,最近发现一篇2017年的论文,感觉不错. 原始论文 https://arxiv.org/pdf/1708.05031.pdf 网上有翻译了 https://www.cnb ...

  5. react + antiDesign开发中遇到的问题记录

    react + antiDesign开发中遇到的问题记录 一:页面中子路由失效: antiDesign的官方实例中,会把路由重复的地方给去重,而且路由匹配模式不是严格模式.所以我们需要在util.js ...

  6. 我眼中的PD(产品狗)

    以下内容可能引起您的不适(前方高能),请先移步科普: 产品经理为什么会存在? 本猿 -> web程序属 -> 前端开发种,从大森林迁徙到了小草原: 小草原物种稀缺,除了 程序猿,很难见到诸 ...

  7. Internet History, Technology and Security (Week5.2)

    Week5 Now, I want to make it real clear that, when I give you a 15 minute video of an amazing invent ...

  8. Eclipse下使用Git

    安装Git 有的eclipse已经自带了Git了,就不用安装了. 如果,想重新安装,可以先卸载git,卸载 不同eclipse卸载不一样: 1.在Eclipse中依次点击菜单"Help&qu ...

  9. Sprint Boot入门(1):创建第一个Spring Boot应用

    搭建工程 注:建议使用eclipse的STS插件创建Spring项目,而不是下面的Gradle项目,否则会导致有一些Spring文件不存在. new Gradle Project,如下 点next,如 ...

  10. fir.im的高级统计功能

    fir.im的高级统计功能,可以根据渠道和活动名称,统计不同渠道和活动带来的下载量.操作步骤如下: 第一步:生成统计链接 点击高级统计,进入统计详情页,然后点击生成统计链接: 设置统计链接的应用版本. ...