bzoj 5287: [Hnoi2018]毒瘤
Description
Solution
\(dfs\) 出一棵生成树之后,多出来的边就都是反祖边了
把反祖边两个端点都拿出来,就会得到最多 \(k=2*(m-n+1)\) 个关键点
除了关键点以外的点转移都是一样的,我们可以预处理出来
关键点数量不多,我们 \(2^k\) 枚举状态,然后像树形 \(DP\) 一样转移就行了
转移需要构一棵虚树,对于虚树上的一条边,对应在原树上的一条链转移也是一样的
如果知道了虚树上 \(x\) 的 \(DP\) 值,\(f[x][0],f[x][1]\),那么就可以推出虚树上的父亲的值 \(f[fa[x]][0],f[fa[x]][1]\)
大致可以表示成这样的形式:\(f[fa[x]][0]=k0*f[x][0]+k1*f[x][1]\),\(f[fa[x]][1]\) 同理
对于转移系数和虚树上某些节点的 \(DP\) 初值都可以 \(O(n*k)\) 的预处理出来
对于一条边 \((x,y)\),只有三种状态:存在 \(x\),存在 \(y\),都不存在,所以状态数实际上只有 \(3^{\frac{k}{2}}\)
复杂度是 \(O(n*k+3^{\frac{k}{2}}*k)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,mod=998244353;
int n,m,head[N],nxt[N*4],to[N*4],num=1,st[N],top=0,sq[N],fa[N][20];
int ST[N*2],TOP=0,dfn[N],DFN=0,tp=0,dep[N],q[N],r=0,Head[N],id[N];
inline bool comp(int i,int j){return dfn[i]<dfn[j];}
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void Link(int x,int y){nxt[++num]=Head[x];to[num]=y;Head[x]=num;}
inline int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int deep=dep[x]-dep[y];
for(int i=19;i>=0;i--)if(deep>>i&1)x=fa[x][i];
if(x==y)return x;
for(int i=19;i>=0;i--)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
bool vis[N],et[N*4];int imp[N],lim,ans=0,f[N][2],lis[N];
struct data{
int k0,k1;
data(){}
data(int _k0,int _k1){k0=_k0;k1=_k1;}
inline data operator +(data &t){return data((k0+t.k0)%mod,(k1+t.k1)%mod);}
inline data operator *(int t){
return data(1ll*k0*t%mod,1ll*k1*t%mod);}
inline int F(int x,int y){return (1ll*x*k0+1ll*y*k1)%mod;}
}k[N][2];
inline void build(int x,int last){
vis[x]=1;dfn[x]=++DFN;
for(int i=head[x];i;i=nxt[i]){
if(i==last)continue;
int u=to[i];
if(!vis[u])fa[u][0]=x,dep[u]=dep[x]+1,build(u,i^1);
else if(dep[u]<dep[x])st[++top]=x,sq[top]=u,et[i]=et[i^1]=1;
}
}
int dp[N][2];bool d[N];
inline void calc(int x,int la){
dp[x][0]=dp[x][1]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(u==la || u==fa[x][0] || d[u])continue;
calc(u,la);
dp[x][0]=1ll*dp[x][0]*(dp[u][0]+dp[u][1])%mod;
dp[x][1]=1ll*dp[x][1]*dp[u][0]%mod;
}
}
inline void getit(int S,int T){
int x=S;
k[x][0]=data(1,0);k[x][1]=data(0,1);
while(fa[x][0]!=T){
calc(fa[x][0],x);
data t=k[S][0];d[fa[x][0]]=1;
k[S][0]=(k[S][0]+k[S][1])*dp[fa[x][0]][0];
k[S][1]=t*dp[fa[x][0]][1];
x=fa[x][0];
}
}
inline void DFS(int x){
for(int i=Head[x];i;i=nxt[i]){
DFS(to[i]);
getit(to[i],x);
}
dp[x][0]=dp[x][1]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(u==fa[x][0] || d[u] || et[i])continue;
calc(u,x);
dp[x][0]=1ll*dp[x][0]*(dp[u][0]+dp[u][1])%mod;
dp[x][1]=1ll*dp[x][1]*dp[u][0]%mod;
}
}
inline void dfs(int x){
f[x][0]=dp[x][0];f[x][1]=dp[x][1];
for(int i=Head[x];i;i=nxt[i]){
int u=to[i],f0,f1;
dfs(u);
f0=k[u][0].F(f[u][0],f[u][1]);
f1=k[u][1].F(f[u][0],f[u][1]);
f[x][0]=1ll*f[x][0]*(f0+f1)%mod;
f[x][1]=1ll*f[x][1]*f0%mod;
}
if(imp[x]!=-1)f[x][imp[x]^1]=0;
}
int main(){
freopen("duliu.in","r",stdin);
freopen("duliu.out","w",stdout);
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
link(x,y);link(y,x);
}
dep[1]=1;build(1,-1);
for(int j=1;j<20;j++)
for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
for(int i=1;i<=top;i++)ST[++TOP]=st[i],ST[++TOP]=sq[i];
sort(ST+1,ST+TOP+1,comp);
tp=unique(ST+1,ST+TOP+1)-ST-1;
int cnt=0;
for(int i=1;i<=tp;i++)lis[++cnt]=ST[i];
lis[++cnt]=1;
sort(lis+1,lis+cnt+1,comp);
cnt=unique(lis+1,lis+cnt+1)-lis-1;
for(int i=1;i<=tp;i++)id[ST[i]]=i-1;
q[++r]=lis[1];
for(int i=2;i<=cnt;i++){
x=lis[i];
int lca=LCA(x,lis[i-1]);d[lca]=1;
while(r && dfn[q[r]]>dfn[lca]){
if(dfn[q[r-1]]>dfn[lca])Link(q[r-1],q[r]);
else {
Link(lca,q[r]);r--;
if(q[r]!=lca)q[++r]=lca;break;
}
r--;
}
q[++r]=lis[i];
}
while(r>1)Link(q[r-1],q[r]),r--;
for(int i=1;i<=cnt;i++)d[lis[i]]=1;
DFS(1);lim=(1<<tp)-1;
memset(imp,-1,sizeof(imp));
for(int i=0;i<=lim;i++){
bool flag=1;
for(int j=1;j<=top;j++)
if((i>>id[st[j]]&1) && (i>>id[sq[j]]&1)){flag=0;break;}
if(!flag)continue;
for(int j=1;j<=tp;j++)imp[ST[j]]=i>>(j-1)&1;
dfs(1);
ans=((ans+f[1][0])%mod+f[1][1])%mod;
}
cout<<ans<<endl;
return 0;
}
bzoj 5287: [Hnoi2018]毒瘤的更多相关文章
- BZOJ 5287: [Hnoi2018]毒瘤 动态dp(LCT+矩阵乘法)
自己 yy 了一个动态 dp 做法,应该是全网唯一用 LCT 写的. code: #include <bits/stdc++.h> #define ll long long #define ...
- 【BZOJ5287】[HNOI2018]毒瘤(动态规划,容斥)
[BZOJ5287][HNOI2018]毒瘤(动态规划,容斥) 题面 BZOJ 洛谷 题解 考场上想到的暴力做法是容斥: 因为\(m-n\le 10\),所以最多会多出来\(11\)条非树边. 如果就 ...
- 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] ...
- [bzoj5287] [HNOI2018]毒瘤
题目描述 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(比如区间加一个数,或者区间开平方),并支持询问区间和.毒瘤考虑了n ...
- [HNOI2018]毒瘤
Description 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(比如区间加一个数,或者区间开平方),并支持询问区间和 ...
- bzoj 5286: [Hnoi2018]转盘
Description Solution 首先注意到一个点不会走两次,只会有停下来等待的情况,把序列倍长 那么如果枚举一个起点\(i\),答案就是 \(min(max(T[j]+n-(j-i)-1)) ...
- bzoj 5285: [Hnoi2018]寻宝游戏
Description Solution 把输入的 \(n\) 个二进制数看作一个大小为 \(n*m\) 的矩阵 把每一列压成一个二进制数,其中最高位是最下面的元素 然后就有了 \(m\) 个二进制数 ...
- bzoj 5289: [Hnoi2018]排列
Description Solution 首先注意到实际上约束关系构成了一棵树 考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现 那么如果连边 \((a[i],i) ...
- bzoj 5288: [Hnoi2018]游戏
Description Solution 乱搞能A的题,毁我青春 记忆化一下扩展过程 只要不是从 \(1\) 枚举到 \(n\) 去扩展都可以 \(AC\) 于是 \(random\_shuffle\ ...
随机推荐
- Beta冲刺NO.2
Beta冲刺 第二天 1.昨天的问题 由于前面的冲刺留下的问题很多,而且混乱的代码给我们接下来的完善工作带来了巨大的困难. 2. 今天解决的进度 潘伟靖: 1.对代码进行了review 2.为系统增加 ...
- Linux kernel 的 sendfile 是如何提高性能的
Linux kernel 的 sendfile 是如何提高性能的 现在流行的 web 服务器里面都提供 sendfile 选项用来提高服务器性能,那到底 sendfile 是什么,怎么影响性能的呢? ...
- 201621123043 《Java程序设计》第7周学习总结
1. 本周学习总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 事件:用户的操作. 事件源:产生事件的组件. 事件监听程序:对事件进行处理的操作所引发的相关 ...
- D的下L
D的小L 时间限制:4000 ms | 内存限制:65535 KB 难度:2 描述 一天TC的匡匡找ACM的小L玩三国杀,但是这会小L忙着哩,不想和匡匡玩但又怕匡匡生气,这时小L给 ...
- JAVA_SE基础——30.构造代码块
黑马程序员入学blog...构造代码块作用:给所有的对象进行统一的初始化. 问题:要求每个小孩出生都会哭,这份代码有两个构造函数,如果需要每个小孩出生都要哭的话,那么就需要在不同的构造函数中都调用cr ...
- 2018年东北农业大学春季校赛-wyh的吃鸡
BFS: 1. 从起点开始BFS,遇到X点则return: 2. vis[px][py][0]代表经过pxpy这点前还没有找到车: vis[px][py][1]代表经过pxpy这点前已经找到车: 3. ...
- ASP.NET Web API编程——路由
路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生 ...
- 第四章 Ajax与jQuery
第四章 Ajax与jQuery 一.Ajax简介 在传统的Web应用中,每次请求服务器都会生成新的页面,用户在提交请求后,总是要等待服务器的响应.如果前一个请求没有响应,则后一个请求就不能发送,在 ...
- Web Uploader初始化隐藏容器失败及点击上传图片时反应较慢的问题
问题1:在一个页面集成一个或者多个文件上传插件,初始化时有些DOM容器是隐藏的,这时候经常会出现初始化失败的情况,虽然按钮样式改变了,但是点击就是没反应(有时候不经意点了哪个地方,或许会出现文件选择框 ...
- jmeter入门(02)测试报告各项指标含义
一.名词定义(时间单位ms) 1.聚合报告 Sample:本次测试场景共运行多少个请求: Average:平均响应时间: Median:统计意义上的响应时间中值: 90% line:所有线程中90%的 ...