题解:P4434 [COCI 2017/2018 #2] ​​Usmjeri

news/2025/10/27 15:47:10/文章来源:https://www.cnblogs.com/TBSF-0207/p/19169290

目前暂无修正。

前置知识:扩展域并查集、树形 DP、离线二维数点(不必要?)。

水个题解,写一个常数大、码量大、难写、简单问题复杂化的思路。时间复杂度 \(O(n\log n+(n+m)\alpha(n))\)

假定树是以 \(1\) 为根的有根树,我们让边权为 \(0\) 表示向下,\(1\) 表示向上。首先设 \(f_{u,0/1}\) 表示以 \(u\) 为根的子树中,\(u\) 与其父亲 \(fa\) 连边权值为 \(0/1\) 的方案数。

考虑转移,发现在输入节点对 \((a_i,b_i)\) 时可以把它挂到 \(lc=\text{LCA}(a_i,b_i)\) 上处理,若 \(lc\neq a_i\land lc\neq b_i\),我们找到 \(lc\) 包含 \(a_i,b_i\) 的子树树根分别记为 \(A,B\),则当 DP 处理 \(lc\)\(f_{A,0}\) 只能和 \(f_{B,1}\) 结合,\(f_{A,1}\) 只能和 \(f_{B,0}\) 结合。

同理,我们发现 \(a_i\to A,b_i\to B\) 这两条链上边权必须都相等。于是我们考虑能否在处理 \(lc\) 时找到在与 \(lc\) 其他子树的点匹配后仍有剩余点的子树,这个东西我不会求所以糊了个离线二维数点上去,通过 DFS 序找出 \(v\)\(u\) 匹配后消掉了多少个点 \(cut_v\),然后再用树上差分算出 \(v\) 子树内原来剩余未匹配点数 \(cnt_v\),如果 \(cnt_v-cut_v>0\) 就存在剩余(具体实现:\((a_i,b_i),(b_i,a_i)\) 单点加,\(cut_v\)\(x\in[dfn_v,dfn_v+siz_v-1]\land y\in[dfn_u,dfn_u+siz_u-1]\text{ 的 }(x,y)\text{ 数量}-x\in[dfn_v,dfn_v+siz_v-1]\land y\in[dfn_v,dfn_v+siz_v-1]\text{ 的 }(x,y)\text{ 数量}\))。

找到的这些 \(v\) 子树一定有 \(f_{v,0}\) 转移到 \(f_{u,0}\)\(f_{v,1}\) 转移到 \(f_{u,1}\)。不妨对每个点设一个状态 \((v,0)\) 代表 \(f_{v,0}\)\((v,1)\) 代表 \(f_{v,1}\),并查集维护连通性,在一个连通块内才能相互结合。只需一开始找到挂在 \(lc\) 上的 \(A,B\) 并连边 \((A,0)-(B,1),(A,1)-(B,0)\)。对于仍有剩余点的子树 \(v_i\) 把所有 \((v_i,0)\) 串起来,\((v_i,1)\) 串起来即可。每个连通块 \(a_X\) 的贡献就是其点权乘积。\(f_{u,0/1}\)\(f_{v_i,0/1}\) 分别强制捆绑,然后每次找到一对连通块 \(X,Y\)(因为连边是对称的),其对 \(f_{u,0/1}\) 都有贡献 \(a_X+a_Y\)。直接转移即可。

最后答案是 \(f_{1,0}\)\(f_{1,1}\),代码不建议参考,仅提供一个构式的思路。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const int N=3e5+5;
int n,m,son[N],dep[N],dfn[N],tms;
int top[N],fat[N],siz[N];
int unc[N],fa[N*2],cut[N];
LL f[N][2];
struct BIT{int av[N];inline int lowbit(int x){return x&-x;}void add(int p,int x){for(int i=p;i<=n;i+=lowbit(i))av[i]+=x;}int que(int p){int res=0;for(int i=p;i;i-=lowbit(i)){res+=av[i];}return res;}
}T;
struct Q{int l,r,id;};
vector<int>G[N],Add[N];
vector<Q>q[N];
inline int fr(int x){return fa[x]==x?x:fa[x]=fr(fa[x]);}
void ins(int x,int y){int frx=fr(x),fry=fr(y);if(frx==fry)return ;fa[frx]=fry;
}
void dfs0(int u,int fa){dep[u]=dep[fa]+1;siz[u]=1;fat[u]=fa;for(int v:G[u]){if(v==fa)continue;dfs0(v,u);siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}
}
void dfs1(int u){dfn[u]=++tms;int fa=fat[u];if(son[fa]==u)top[u]=top[fa];else top[u]=u;if(son[u])dfs1(son[u]);for(int v:G[u]){if(v==fa||v==son[u])continue;dfs1(v);}
}
int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=fat[top[x]];}if(dep[x]>dep[y])swap(x,y);return x;
}
int jump(int x,int y){int last=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);last=top[x],x=fat[top[x]];}if(dep[x]>dep[y])swap(x,y);if(x==y)return last;return son[x];
}
bool vis[N*2];
void dfs(int u){int fa=fat[u],ex=0;for(int v:G[u]){if(v==fa)continue;dfs(v);unc[u]+=unc[v];if(unc[v]-cut[v]>0)ex=v;}if(!son[u])f[u][0]=1,f[u][1]=1;else {bool tf=1;for(int v:G[u]){if(v==fa)continue;if(fr(v)==fr(v+n)){tf=0;break;}if(unc[v]-cut[v]>0)ins(v,ex),ins(v+n,ex+n);}if(!tf){f[u][0]=f[u][1]=0;return ;}for(int v:G[u]){if(v==fa)continue;if(fr(v)>n)f[fr(v)-n][1]=f[fr(v)-n][1]*f[v][0]%MOD;else if(fr(v)!=v)f[fr(v)][0]=f[fr(v)][0]*f[v][0]%MOD;if(fr(v+n)<=n)f[fr(v+n)][0]=f[fr(v+n)][0]*f[v][1]%MOD;else if(fr(v+n)!=v+n)f[fr(v+n)-n][1]=f[fr(v+n)-n][1]*f[v][1]%MOD;}int frex=0,frexn=0;if(ex){frex=fr(ex),frexn=fr(ex+n);vis[frex]=vis[frexn]=1;f[u][0]=(frex<=n?f[frex][0]:f[frex-n][1]);f[u][1]=(frexn<=n?f[frexn][0]:f[frexn-n][1]);}else f[u][0]=f[u][1]=1;for(int v:G[u]){if(v==fa)continue;assert(!(vis[fr(v)]^vis[fr(v+n)]));if(vis[fr(v)]||vis[fr(v+n)])continue;vis[fr(v)]=vis[fr(v+n)]=1;int a=fr(v),b=fr(v+n);bool ga=0,gb=0;if(a>n)a-=n,ga=1;if(b>n)b-=n,gb=1;f[u][0]=f[u][0]*(f[a][ga]+f[b][gb])%MOD;f[u][1]=f[u][1]*(f[a][ga]+f[b][gb])%MOD;}}
}
int main(){//freopen("dispatch.in","r",stdin);//freopen("dispatch.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=2*n;i++)fa[i]=i;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);G[u].emplace_back(v);G[v].emplace_back(u); }dfs0(1,0);dfs1(1);for(int i=2;i<=n;i++){int v=i,u=fat[v];q[dfn[v]-1].emplace_back(Q{dfn[u],dfn[u]+siz[u]-1,-v});q[dfn[v]+siz[v]-1].emplace_back(Q{dfn[u],dfn[u]+siz[u]-1,v});q[dfn[v]-1].emplace_back(Q{dfn[v],dfn[v]+siz[v]-1,v});q[dfn[v]+siz[v]-1].emplace_back(Q{dfn[v],dfn[v]+siz[v]-1,-v});}for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);Add[dfn[a]].emplace_back(dfn[b]);Add[dfn[b]].emplace_back(dfn[a]);int lc=LCA(a,b);unc[a]++;unc[b]++;unc[lc]-=2;if(lc!=a&&lc!=b){a=jump(a,lc);b=jump(b,lc);ins(a,b+n);ins(b,a+n);}}for(int i=1;i<=n;i++){for(int v:Add[i])T.add(v,1);for(Q v:q[i]){if(v.id>0)cut[v.id]+=T.que(v.r)-T.que(v.l-1);else cut[-v.id]-=T.que(v.r)-T.que(v.l-1);}}dfs(1);printf("%lld",f[1][0]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/947789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《CSS盒子模型》笔记总结 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025修护洗/二硫化硒去屑/香氛/控油蓬松/洗发水品牌推荐:MASIL玛丝兰引领功效细分赛道,哪个牌子好?看实测口碑榜

在头皮护理需求日益精细化的 2025 年,洗发水已从基础清洁升级为 “精准功效 + 温和养护” 的综合方案。以下结合成分科技与用户口碑,推荐兼具专业性与适配性的洗发水品牌,看看哪个牌子好。 西安悦己容生物科技有限责…

2025 年 10 月仓库管理系统软件,电商仓库管理系统,云仓库管理系统公司最新推荐,技术实力与市场口碑深度解析!

引言 在数字化转型浪潮下,仓库管理系统已成为企业供应链的核心基建,市场需求持续攀升,相关市场年复合增长率预计保持在 22% 以上。然而,多平台订单协同难、场景适配性不足、数据孤岛等问题仍困扰着众多企业。为助力…

小程序-跳转到公众号

从小程序跳转到公众号的方法 最简单的方式,可能会出现偶现的情况<official-account></official-account>建议用下面wx.openOfficialAccountProfile({username: gh_123123, // 此处填写公众号的原始 IDsuc…

如何解决一堆向量的问题?10、Self-attention - -一叶知秋

接CNN 如何解决一堆向量的问题? 输入 一个单词一个编码,一句话是一堆向量声音信号是一堆向量一个图也是一堆向量输出 输入多少,输出多少(Sequence labeling)输入很多,输出一个输入很多,但不知道输出多少,让机器…

Personalities Test – Free 16 Personalities (MBTI) Personality Test Online

Personalities Test is a free online platform designed to help you discover your true personality type based on the MBTI (Myers-Briggs Type Indicator) framework. By answering a series of carefully desig…

win11系统优化(右键鼠标选项功能太多)

1. 右键菜单(Win10经典菜单)功能:恢复Win10的经典菜单 。 恢复方法:按住 win + r 输入 cmd,打开命令提示符,想变哪个就输入哪个的命令!恢复Win10经典菜单命令 1 reg add "HKEY_CURRENT_USER\SOFTWARE\CLAS…

2025 年 10 月跨境新零售系统,微商新零售系统,商城新零售系统公司最新推荐,技术实力与市场口碑深度解析

引言 2025 年零售数字化转型进入深水区,跨境、微商、商城三大细分领域的系统需求激增,据零售联合会(NRF)报告显示,超 60% 的零售销售与数字技术深度绑定,而跨境业务因合规、物流等痛点,系统适配率仅 35%。为精准…

模拟赛 R19

R19 - A 过去 题目描述 你有一个长度为 \(n\) 的排列 \(p_1,p_2\sim p_n\),初始时 \(p_i=i\)。 接下来你进行了 \(m\) 次操作,第 \(i\) 次操作翻转了前缀 \(p_1,p_2\sim p_{a_i}\),即如果记 \(b_j=p_j\),那么新的 …

win10激活脚本

新建txt文件 slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX slmgr /skms kms.loli.best slmgr /ato 将文件后缀改为bat后右键文件管理员执行本帖子也是纯手工制作,转载请标明出处-----------burukku(づ。◕ᴗᴗ◕。)づ

MCS-51中断系统

MCS-51中断系统1、微型计算机和外部设备之间的传送方式 同步传送,异步传送,中断传送,DMA(直接内存储器存储) 2、中断的定义 定义:计算机暂时停止原程序的执行转而为外部设备服务(执行中断服务程序),并在服务完…

2025 年智慧新零售系统,新零售系统服务商,新零售系统 ERP 公司最新推荐,聚焦资质、案例、售后的实力品牌深度解析!

引言 随着 AI 数字化零售的蓬勃发展,全渠道协同与精细化运营已成为零售企业转型的核心诉求。为精准筛选兼具技术实力与服务能力的系统服务商,本次测评联合行业权威机构,基于三大核心维度展开全面评估:在资质维度,…

AOP面向切面编程思想

AOP切面编程思想 ​ AOP(Aspect-Oriented Programming)是一种编程范式(面向切面编程),通过横向抽取机制将分散在各个模块中的公共关注点(如日志、事务、权限)分离出来,形成独立的切面(Aspect),从而提高代码的…

阿里巴巴 AI Coding 分享会 Qoder Together 杭州站来啦!

与 Qoder 技术团队面对面,聊聊产品背后的设计理念与未来规划 听资深用户分享使用 Qoder 的实战经验与技巧 现场 AI Coding 黑客松,一起体验智能编程的新范式,边写边学边碰撞点击此处或下方链接立即报名: https://w…

2025 年分销供应链系统、供应链系统软件、供应链系统 SaaS 公司最新推荐,技术实力与市场口碑深度解析!

引言 在数字化转型加速推进的当下,供应链管理软件已成为企业优化运营效率的核心工具,据行业调研显示,2024 年超 67% 的企业因供应链管理不善导致至少 15% 的利润损失。为精准筛选优质供应链系统服务商,本次测评联合…

洞悉过往,一目了然:浅述视频融合平台EasyCVR如何实现海量视频录像的智能检索与高效回看

洞悉过往,一目了然:浅述视频融合平台EasyCVR如何实现海量视频录像的智能检索与高效回看引言:从“看实时”到“查过往”的核心价值 在视频监控领域,实时直播让我们掌控当下,而录像回看功能则让我们能够洞悉过往,是…

C#性能暴增300%!这10个黑科技代码你绝对没用过

C#性能暴增300%!这10个黑科技代码你绝对没用过Posted on 2025-10-27 15:35 lzhdim 阅读(0) 评论(0) 收藏 举报在C# 开发的广袤天地里,你是否常常渴望能有一种神奇的力量,让代码的性能实现飞跃式提升?今天,就…

如何找到心仪的 ChatBI 智能体?Aloudata Agent 推荐给你

Aloudata Agent 凭借其技术架构的创新性、分析能力的闭环性以及场景适配的深度,成为企业落地ChatBI、实现数据驱动决策的理想选择。在数智化转型浪潮中,ChatBI 智能体凭借自然语言交互能力,成为企业打破数据分析壁垒…

10月第二篇

《程序员修炼之道:从小工到专家》阅读笔记 第二阶段:“破窗理论” 与代码质量守护 “破窗理论” 应该是书里讲代码质量最戳我的点了,它不是干巴巴的理论,而是说到了我们小组做项目时常见的 “摆烂” 问题。书里打了…

2025年国内外五款AI编程工具深入对比与推荐排行

当 “写代码” 从 “手动敲” 变成 “AI 帮你想”,研发效率的天花板被彻底打破。2025 年最新出炉的 AI 编程工具排名,不仅是技术实力的较量,更是企业降本增效的 “选型指南”—— 这 5 款工具,已经帮数万家企业实现…