1 条题解
-
0
自动搬运
来自洛谷,原作者为

xieziheng
还不是因为我动了资本的蛋糕搬运于
2025-08-24 23:00:09,当前版本为作者最后更新于2024-06-30 12:11:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这题真的只有蓝吗。。。看来是我太菜了
不过我竟然场切了 dp,感到震惊。
这个题首先要选择一个好算的东西计数,如果考虑对每个 算 的方案就很不好搞,所以反过来,考虑对每个 算有多少个 满足条件。 是平凡的,一下设 。
先看树的情况,是显然的, 中的点必定在 中所有点构成的虚树中,且这是充要的,换言之,设 中点构成的虚树大小为 ,则共有 的 满足条件。
考虑推广。发现“简单路径”很像点双相关(说句闲话,我比赛以为简单路径指的是边不重复)。于是大胆猜测构成的是所有有 中路径经过的点双的并集大小。证明是容易的,由点双性质可知。
所以考虑建出圆方树 dp。这时候就需要给圆方树上每个点赋权,使得答案容易计算。发现可以这样赋值:对于圆点,权值为 ,对于方点 ,权值为 , 表示第 个点双的大小。这样所有有 中路径经过的点双的并集大小即为所有 中的点在圆方树上构成的虚树中的点的权值和加一,设这个玩意为 。即求 。
考虑 dp,设 表示虚树根为 的方案数。考虑合并子树状态,一定为选择若干个在 的不同子树的点,然后对其求和。设 表示对于 为 的祖先, 到 路径上的权值和(不包含 ),设 , 表示 的子树构成的集合,同理定义 表示 所有儿子构成的集合。
-
为方点,则一定为选择大于等于 个子树中的点合并。则 $f_x=2^{s_x-1}((\prod_{y\in T_x}(1+t_y))-1-\sum_{y\in T_x}t_y),t_x=2^{s_x-1}\sum_{y\in T_x}t_y$。
-
为原点,则 $f_x=(2\prod_{y\in T_x}(1+t_y))- 1-\sum_{y\in T_x}t_y$。
这样就做完了,复杂度
细节见代码:
#include <bits/stdc++.h> #define il inline using namespace std; typedef long long ll; const ll mod=998244353; il int read(){ int x=0,c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-48,c=getchar(); return x; } il void add(ll &x,ll y){x=(x+y>=mod?x+y-mod:x+y);} const int N=1e6+5; int n,m,dfn[N],low[N],cnt,st[N],top,bel[N],idx,siz[N];ll ans,pw[N],f[N],s[N],t[N]; vector<int> e[N],g[N]; il void adde(int x,int y,vector<int> e[]){e[x].push_back(y),e[y].push_back(x);} void tarjan(int x,int fath){ int y,z;dfn[x]=low[x]=++cnt,st[++top]=x; for(int y:e[x]){ if(y==fath) continue; if(!dfn[y]){ tarjan(y,x),low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]){ ++idx,adde(idx+n,x,g),bel[x]=idx,siz[idx+n]=1; do{ z=st[top--],bel[z]=idx,adde(idx+n,z,g),++siz[idx+n]; }while(z!=y); } } else low[x]=min(low[x],dfn[y]); } } void dfs(int x,int fath){ if(x>1 && g[x].size()==1){ f[x]=s[x]=t[x]=1; return ; } ll u=0,v,w=1ll; for(int y:g[x]){ if(y==fath) continue; dfs(y,x),add(s[x],s[y]); } if(x>n){ for(int y:g[x]){ if(y==fath) continue; add(u,t[y]),w=(w*(1ll+t[y]))%mod,t[x]=(t[x]+pw[siz[x]-1]*t[y])%mod; } f[x]=((w-1ll-u+mod)*pw[siz[x]-1])%mod; } else{ for(int y:g[x]){ if(y==fath) continue; add(u,t[y]),w=(w*(1ll+t[y]))%mod,add(t[x],t[y]); } f[x]=(u+(w-u+mod)*2ll-1)%mod; } add(s[x],f[x]),add(t[x],f[x]); } int x,y,z;ll u,v,w; int main(){ scanf("%d%d",&n,&m);pw[0]=1ll; for(int i=1;i<=n;++i) pw[i]=(pw[i-1]*2ll)%mod; for(int i=1;i<=m;++i) x=read(),y=read(),adde(x,y,e),adde(y,x,e); tarjan(1,0); dfs(1,0); for(int i=1;i<=n+idx;++i) add(ans,f[i]); printf("%lld",(2ll*ans+1ll)%mod); return 0; } -
- 1
信息
- ID
- 10429
- 时间
- 3000ms
- 内存
- 1024MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者