虚树+dp

直接看zlttttt的强大题解 zlttttt的题解看这里

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=100010+10,Mod=998244353;
int n,m,e,to[MAXM<<1],nex[MAXM<<1],beg[MAXN],w[MAXM<<1],Jie[MAXN][20],dfn,dfsrk[MAXN],st[MAXN],ed[MAXN],dep[MAXN],cnt,Idfn,Icnt,Istack[MAXN],Ist[MAXN],Idfsrk[MAXN],slt[MAXN],Ipoint[MAXN],In,Ie,Ibeg[MAXN],Inex[MAXM<<1],Ito[MAXM<<1],f[MAXN][2],lmt[MAXN],g[MAXN][2];
std::pair<int,int> stack[MAXM];
struct data{
int k0,k1;
data(int a=0,int b=0){
k0=a,k1=b;
}
inline data operator + (const data &A) const {
return data(k0+A.k0,k1+A.k1);
};
inline data operator * (const int a) const {
return data(1ll*k0*a%Mod,1ll*k1*a%Mod);
};
inline int value(int a,int b){
return (1ll*a*k0%Mod+1ll*b*k1%Mod)%Mod;
};
};
data coeffi[MAXN][2];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
w[e]=1;
}
inline void dfs1(int x,int f)
{
dep[x]=dep[f]+1;Jie[x][0]=f;
dfsrk[st[x]=++dfn]=x;
for(register int i=beg[x];i;i=nex[i])
if(to[i]==f)w[i]=0;
else
{
if(!dep[to[i]])dfs1(to[i],x);
else w[i]=0,stack[++cnt]=std::pair<int,int>(min(x,to[i]),max(x,to[i]));
}
ed[x]=dfn;
}
inline bool cmp(int a,int b)
{
return st[a]<st[b];
}
inline int LCA(int u,int v)
{
if(dep[u]<dep[v])std::swap(u,v);
if(dep[u]>dep[v])
for(register int i=19;i>=0;--i)
if(dep[Jie[u][i]]>=dep[v])u=Jie[u][i];
if(u==v)return u;
for(register int i=19;i>=0;--i)
if(Jie[u][i]!=Jie[v][i])u=Jie[u][i],v=Jie[v][i];
return Jie[u][0];
}
inline void Iinsert(int x,int y)
{
Ito[++Ie]=y;
Inex[Ie]=Ibeg[x];
Ibeg[x]=Ie;
}
inline void dfs3(int x,int tp)
{
f[x][0]=f[x][1]=1;
for(register int i=beg[x];i;i=nex[i])
if(to[i]!=Jie[x][0]&&to[i]!=tp&&!slt[to[i]])
{
dfs3(to[i],tp);
f[x][0]=1ll*f[x][0]*((f[to[i]][0]+f[to[i]][1])%Mod)%Mod;
f[x][1]=1ll*f[x][1]*f[to[i]][0]%Mod;
}
}
inline void calc(int s,int t)
{
coeffi[s][0]=data(1,0);coeffi[s][1]=data(0,1);
data now;
for(register int i=s;Jie[i][0]!=t;i=Jie[i][0])
{
dfs3(Jie[i][0],i);
slt[Jie[i][0]]=1;
now=coeffi[s][0];
coeffi[s][0]=(coeffi[s][0]+coeffi[s][1])*f[Jie[i][0]][0];
coeffi[s][1]=now*f[Jie[i][0]][1];
}
}
inline void dfs2(int x)
{
for(register int i=Ibeg[x];i;i=Inex[i])dfs2(Ito[i]),calc(Ito[i],x);
f[x][0]=f[x][1]=1;
for(register int i=beg[x];i;i=nex[i])
if(!slt[to[i]]&&to[i]!=Jie[x][0]&&w[i]>0)
{
dfs3(to[i],0);
f[x][0]=1ll*f[x][0]*((f[to[i]][0]+f[to[i]][1])%Mod)%Mod;
f[x][1]=1ll*f[x][1]*f[to[i]][0]%Mod;
}
}
inline void dfs4(int x)
{
g[x][0]=f[x][0];
g[x][1]=f[x][1];
for(register int i=Ibeg[x],k0,k1;i;i=Inex[i])
{
dfs4(Ito[i]);
k0=coeffi[Ito[i]][0].value(g[Ito[i]][0],g[Ito[i]][1]);
k1=coeffi[Ito[i]][1].value(g[Ito[i]][0],g[Ito[i]][1]);
g[x][0]=1ll*g[x][0]*((k0+k1)%Mod)%Mod;
g[x][1]=1ll*g[x][1]*k0%Mod;
}
if(~lmt[x])g[x][lmt[x]^1]=0;
}
int main()
{
freopen("duliu.in","r",stdin);
freopen("duliu.out","w",stdout);
read(n);read(m);
for(register int i=1;i<=m;++i)
{
int u,v;
read(u);read(v);
insert(u,v);insert(v,u);
}
dep[1]=1;
dfs1(1,0);
for(register int j=1;j<20;++j)
for(register int i=1;i<=n;++i)Jie[i][j]=Jie[Jie[i][j-1]][j-1];
std::sort(stack+1,stack+cnt+1);
cnt=std::unique(stack+1,stack+cnt+1)-stack-1;
for(register int i=1;i<=cnt;++i)
{
if(!slt[stack[i].first])
{
slt[stack[i].first]=1;
Ipoint[++In]=stack[i].first;
Ist[Idfsrk[++Idfn]=stack[i].first]=Idfn;
}
if(!slt[stack[i].second])
{
slt[stack[i].second]=1;
Ipoint[++In]=stack[i].second;
Ist[Idfsrk[++Idfn]=stack[i].second]=Idfn;
}
}
std::sort(Ipoint+1,Ipoint+In+1,cmp);
for(register int i=2,limit=In;i<=limit;++i)Ipoint[++In]=LCA(Ipoint[i-1],Ipoint[i]);
Ipoint[++In]=1;
std::sort(Ipoint+1,Ipoint+In+1,cmp);
In=std::unique(Ipoint+1,Ipoint+In+1)-Ipoint-1;
Istack[++Icnt]=Ipoint[1];
for(register int i=2;i<=In;++i)
if(Icnt)
{
while(Icnt&&ed[Istack[Icnt]]<st[Ipoint[i]])Icnt--;
Iinsert(Istack[Icnt],Ipoint[i]);
Istack[++Icnt]=Ipoint[i];
}
for(register int i=1;i<=In;++i)slt[Ipoint[i]]=1;
dfs2(1);
for(register int i=1;i<=n;++i)lmt[i]=-1;
int ans=0;
for(register int i=(1<<Idfn)-1;i>=0;--i)
{
int mark=0;
for(register int j=1;j<=cnt;++j)
if((i>>(Ist[stack[j].first]-1)&1)&&(i>>(Ist[stack[j].second]-1)&1))
{
mark=1;
break;
}
if(mark)continue;
for(register int j=1;j<=Idfn;++j)lmt[Idfsrk[j]]=(i>>(j-1))&1;
dfs4(1);
(ans+=(g[1][0]+g[1][1])%Mod)%=Mod;
}
write(ans,'\n');
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. HNOI2018毒瘤

    题面链接 luogu sol 这篇博是骗访问量的QwQ. 考虑树怎么做,简单容斥.诸如\(f[u][0]=\prod (f[v][0]+f[v][1]),f[u][1]=\prod f[v][0]\) ...

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

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

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

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

随机推荐

  1. 修改索引名称(mysql)

    MySQL修改索引名称. 对于MySQL 5.7及以上版本,可以执行以下命令: ALTER TABLE tbl_name RENAME INDEX old_index_name TO new_inde ...

  2. javaweb(二十四)——jsp传统标签开发

    一.标签技术的API 1.1.标签技术的API类继承关系 二.标签API简单介绍 2.1.JspTag接口 JspTag接口是所有自定义标签的父接口,它是JSP2.0中新定义的一个标记接口,没有任何属 ...

  3. https双向认证网站搭建

    新建网站 在搭建网站证书之前,我们先搭建好我们的网站 1.网站基本搭建 为我们的项目新建一个网站,按照如下的步骤来 1,打开IIS,右键单击网站弹出菜单,选择网站(如图1.1.1) 图1.1.1 2, ...

  4. 初次学习asp.net core的心得

    初次学习Asp.Net Core方面的东西,虽然研究的还不是很深,今天主要是学习了一下Asp.Net Core WebAPI项目的使用,发现与Asp.Net WebAPI项目还是有很多不同.不同点包含 ...

  5. nginx 日志模块

    ngx_http_log_module.c 数据结构 typedef struct { void **main_conf; void **srv_conf; void **loc_conf;} ngx ...

  6. 论文笔记:Fully-Convolutional Siamese Networks for Object Tracking

    Fully-Convolutional Siamese Networks for Object Tracking 本文作者提出一个全卷积Siamese跟踪网络,该网络有两个分支,一个是上一帧的目标,一 ...

  7. 《Learning scikit-learn Machine Learning in Python》chapter1

    前言 由于实验原因,准备入坑 python 机器学习,而 python 机器学习常用的包就是 scikit-learn ,准备先了解一下这个工具.在这里搜了有 scikit-learn 关键字的书,找 ...

  8. Github上的一些高分Qt开源项目【多图】

    游戏2D地图编辑器: 著名的TileMap编辑器,做2D游戏开发的一定不会陌生. Go 语言的IDE: Go语言的集成开发环境. Clementine Music Player: 功能很完善且跨平台支 ...

  9. A Product Recall 产品召回

    Rick: The Board of Directors has come to a decision. Our company will take an image hit, and it's go ...

  10. c# 加载图片 正在被占用问题

    问题情境:图片文件加载到pdf中,程序没有退出,再次加载该图片文件,提示被占用. 解决办法: 1.加载文件会锁定该文件,fromfile方法会导致占用内存较大,不使用该方法. FileStream f ...