题面链接

luogu

sol

这篇博是骗访问量的QwQ。

考虑树怎么做,简单容斥。诸如\(f[u][0]=\prod (f[v][0]+f[v][1]),f[u][1]=\prod f[v][0]\)

考虑\(80\)分怎么做(其实只有\(75\)分),暴力枚举多出来的边链接情况,然后\(dp\),复杂度\(O(2^{m-n+1}n)\)。

考虑\(100\)分怎么做,发现只有\(22\)个有用的点,于是建虚树,预处理转移系数,有点复杂。复杂度\(O((m-n+1)*2^{m-n+1}+n)\)

upd:系数大概是个\(f[u][i]=\sum w[u->v][j][i]*f[v][j]\)。自己YY一下就好了,可以拓展到多维系数。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define gt getchar()
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
inline int in()
{
int k=0;char ch=gt;
while(ch<'-')ch=gt;
while(ch>'-')k=k*10+ch-'0',ch=gt;
return k;
}
const int N=2e5+5,YL=998244353;
int f[N][2],fg[N][2],le[N],ri[N],top;
int head[N],to[N<<1],nxt[N<<1],cnt,imp[N];
inline void add(int u,int v)
{
to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
to[++cnt]=u,nxt[cnt]=head[v],head[v]=cnt;
}
inline int MO(const int &a){return a>=YL?a-YL:a;}
int dfn[N],low[N],tt,tsz[N];
void dfs(int u,int pa=0)
{
dfn[u]=++tt;
for(int i=head[u];i;i=nxt[i])
if(to[i]!=pa)
{
if(!dfn[to[i]])dfs(to[i],u),tsz[u]+=tsz[to[i]];
else if(dfn[u]<dfn[to[i]])le[++top]=u,ri[top]=to[i],imp[u]=1;
else imp[u]=1;
}
imp[u]|=tsz[u]>=2;tsz[u]=imp[u]||tsz[u];
}
int o[N];
int Head[N],To[N],Nxt[N];
struct bj
{
int x,y;
bj(){x=0,y=0;}
bj(int _x,int _y):x(_x),y(_y){}
inline bj operator+(const bj &a){return bj(x+a.x,y+a.y);}
inline bj operator*(const int &a){return bj(1ll*x*a%YL,1ll*y*a%YL);}
}W1[50],W2[50],k[N][2];
inline void Add(int u,int v,bj a,bj b){To[++cnt]=v,Nxt[cnt]=Head[u],W1[cnt]=a,W2[cnt]=b,Head[u]=cnt;}
int g[N][2];
int Dfs(int u,int pa=0)
{
g[u][0]=g[u][1]=1;o[u]=1;int pos=0,w;
for(int i=head[u];i;i=nxt[i])
if(!o[to[i]])
{
int v=to[i];w=Dfs(v);
if(!w)g[u][1]=1ll*g[u][1]*g[v][0]%YL,g[u][0]=1ll*g[u][0]*(g[v][1]+g[v][0])%YL;
else if(imp[u])Add(u,w,k[v][0]+k[v][1],k[v][0]);
else k[u][1]=k[v][0],k[u][0]=k[v][1]+k[v][0],pos=w;
}
if(imp[u])k[u][0]=bj(1,0),k[u][1]=bj(0,1),pos=u;
else k[u][0]=k[u][0]*g[u][0],k[u][1]=k[u][1]*g[u][1];
return pos;
}
void dp(int u)
{
f[u][0]=fg[u][1]?0:g[u][0];
f[u][1]=fg[u][0]?0:g[u][1];
for(int i=Head[u];i;i=Nxt[i])
{
int v=To[i];dp(v);int p=f[v][0],q=f[v][1];
f[u][1]=1ll*f[u][1]*(1ll*W2[i].x*p%YL+1ll*W2[i].y*q%YL)%YL;
f[u][0]=1ll*f[u][0]*(1ll*W1[i].x*p%YL+1ll*W1[i].y*q%YL)%YL;
}
}
int main()
{
int n=in(),m=in();
for(int i=1;i<=m;++i)add(in(),in());cnt=0;
dfs(1);imp[1]=1;Dfs(1);
int S=1<<top,ans=0;
for(int i=0;i<S;++i)
{
for(int j=0;j<top;++j)
if(i>>j&1)fg[le[j+1]][1]=fg[ri[j+1]][0]=1;
else fg[le[j+1]][0]=1;
dp(1);ans=MO(ans+MO(f[1][1]+f[1][0]));
for(int j=0;j<top;++j)
if(i>>j&1)fg[le[j+1]][1]=fg[ri[j+1]][0]=0;
else fg[le[j+1]][0]=0;
}
printf("%d\n",ans);
return 0;
}

HNOI2018毒瘤的更多相关文章

  1. 【BZOJ5287】[HNOI2018]毒瘤(动态规划,容斥)

    [BZOJ5287][HNOI2018]毒瘤(动态规划,容斥) 题面 BZOJ 洛谷 题解 考场上想到的暴力做法是容斥: 因为\(m-n\le 10\),所以最多会多出来\(11\)条非树边. 如果就 ...

  2. [bzoj5287] [HNOI2018]毒瘤

    题目描述 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(比如区间加一个数,或者区间开平方),并支持询问区间和.毒瘤考虑了n ...

  3. [HNOI2018]毒瘤

    Description 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(比如区间加一个数,或者区间开平方),并支持询问区间和 ...

  4. bzoj 5287: [Hnoi2018]毒瘤

    Description Solution \(dfs\) 出一棵生成树之后,多出来的边就都是反祖边了 把反祖边两个端点都拿出来,就会得到最多 \(k=2*(m-n+1)\) 个关键点 除了关键点以外的 ...

  5. BZOJ.5287.[AHOI HNOI2018]毒瘤(虚树 树形DP)

    BZOJ LOJ 洛谷 设\(f[i][0/1]\)表示到第\(i\)个点,不选/选这个点的方案数.对于一棵树,有:\[f[x][0]=\prod_{v\in son[x]}(f[v][0]+f[v] ...

  6. BZOJ5287 HNOI2018毒瘤(虚树+树形dp)

    显然的做法是暴力枚举非树边所连接两点的选或不选,大力dp.考场上写的是最暴力的O(3n-mn),成功比大众分少10分.容斥或者注意到某些枚举是不必要的就能让底数变成2.但暴力的极限也就到此为止. 每次 ...

  7. [BZOJ5287][HNOI2018]毒瘤(虚树DP)

    暴力枚举非树边取值做DP可得75. 注意到每次枚举出一个容斥状态的时候,都要做大量重复操作. 建立虚树,预处理出虚树上两点间的转移系数.也可动态DP解决. 树上倍增.动态DP.虚树DP似乎是这种问题的 ...

  8. 【比赛】HNOI2018 毒瘤

    虚树+dp 直接看zlttttt的强大题解 zlttttt的题解看这里 #include<bits/stdc++.h> #define ui unsigned int #define ll ...

  9. BZOJ 5287: [Hnoi2018]毒瘤 动态dp(LCT+矩阵乘法)

    自己 yy 了一个动态 dp 做法,应该是全网唯一用 LCT 写的. code: #include <bits/stdc++.h> #define ll long long #define ...

随机推荐

  1. C#_Switch语句的内部实现

    Switch的C#内部实现 https://www.cnblogs.com/Interkey/p/3730432.html 在IL汇编语言中的Switch指令 -- 按照标号来进行跳转(和goto语句 ...

  2. 0.3 CMD常用命令!以及用CMD显得自己高大上

    CMD是大家熟知的Windows命令提示符(cmd.exe),它是 Windows NT 下的一个用于运行 Windows 控制面板程序或某些 DOS 程序的shell程序. CMD命令快捷键是:wi ...

  3. jar包、war包

    JavaSE程序可以打包成Jar包(J其实可以理解为Java了),而JavaWeb程序可以打包成war包(w其实可以理解为Web了).然后把war发布到Tomcat的webapps目录下,Tomcat ...

  4. [文章存档]Kudu 的 Debug Console 窗口如何查看更多文件

    链接:https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-h ...

  5. string类型和int类型之间的转换

    一.string转int 1. 使用string流 /* 字符串转整型 */ /* * istringstream:从 string 读取数据 * ostringstream:向 string 写入数 ...

  6. NEWBEE软件团队 人员分配情况及分数获得方式

    人员分配: PM:李桐  王骜 dev:王骜 刘垚鹏 安康  林旭鹏  黄新越 test:黄伟龙 李桐 马佐霖 黄新越 注:黄新越为女生,不方便平时的交流,所以任务分配较为灵活,特分在两个组里. 评分 ...

  7. 团队博客作业Week1 --- 团队成员简介

    团队博客作业Week1 团队作业1 我们团队是一个以功能团队模式组建而成的团队,我们总共有5位队员,分别是:李剑锋.陈谋.卢惠明.潘成鼎.仉伯龙. 中间的那位就是李剑锋,我们的PM(项目经理).性格热 ...

  8. oracle 语句之对数据库的表名就行模糊查询,对查询结果进行遍历,依次获取每个表名结果中的每个字段(存储过程)

    语句的执行环境是plsql的sql窗口, 语句的目的是从整个数据库中的所有表判断 不等于某个字段的记录数 . 代码如下: declare s_sql clob:=''; -- 声明一个变量,该变量用于 ...

  9. 进阶系列(4)—— C#文件与流

    一. 驱动器 在Windows操作系统中,存储介质统称为驱动器,硬盘由于可以划分为多个区域,每一个区域称为一个驱动器..NET Framew   ork提供DriveInfo类和 DriveType枚 ...

  10. keras+theano+tensorflow+darknet

    keras 安装: 最好在anaconda的虚拟环境下搭建: conda create -n 环境名 python=3.6 进入环境: source activate 环境名 安装keras: pip ...