BZOJ 2286 树链剖分+DFS序+虚树+树形DP
第一次学习虚树,就是把无关的点去掉。S里维护一条链即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
const LL Maxm=;
const LL Maxn=;
const LL Inf=1e60;
struct Node {LL to,next,w;}edge[Maxm],edge2[Maxm];
LL head[Maxn],head2[Maxn],dep[Maxn],H[Maxn],mark[Maxn],size[Maxn];
LL top[Maxn],father[Maxn],f[Maxn],S[Maxn],mn[Maxn];
LL cnt1,cnt2,tot,n,u,v,w,tp,m,K;
bool vis[Maxn];
inline void Add(LL u,LL v,LL w)
{edge[cnt1].to=v;edge[cnt1].next=head[u];edge[cnt1].w=w;head[u]=cnt1++;
edge[cnt1].to=u;edge[cnt1].next=head[v];edge[cnt1].w=w;head[v]=cnt1++;}
inline void Add2(LL u,LL v)
{if (u==v) return; edge2[cnt2].to=v;edge2[cnt2].next=head2[u];head2[u]=cnt2++;}
inline LL Min(LL x,LL y) {return x>y?y:x;}
inline void Get_Int(LL &x)
{
x=; char ch=getchar(); LL f=;
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();} x*=f;
}
inline void Put_Int(LL x)
{
char ch[]; LL top=;
if (x==) ch[++top]='';
while (x) ch[++top]=x%+'',x/=;
while (top) putchar(ch[top--]); putchar('\n');
}
//================================================
void Dfs1(LL u)
{
mark[u]=++tot;vis[u]=true; size[u]=;
for (LL i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to])
{
dep[edge[i].to]=dep[u]+;
father[edge[i].to]=u;
mn[edge[i].to]=Min(mn[u],edge[i].w);
Dfs1(edge[i].to);
size[u]+=size[edge[i].to];
}
}
void Dfs2(LL u,LL chain)
{
top[u]=chain; vis[u]=true; LL k=;
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && (size[edge[i].to]>size[k] || k==)) k=edge[i].to;
if (k==) return;
Dfs2(k,chain);
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && i!=k) Dfs2(edge[i].to,edge[i].to);
}
inline LL Lca(LL u,LL v)
{
while (true)
{
if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
if (dep[top[u]]>dep[top[v]]) u=father[top[u]];
else v=father[top[v]];
}
}
//=============================================================
inline bool cmp(LL x,LL y) {return mark[x]<mark[y];}
void Dp(LL u)
{ vis[u]=true; f[u]=mn[u]; LL ret=;
for (int i=head2[u];i!=-;i=edge2[i].next)
{
Dp(edge2[i].to);
ret+=f[edge2[i].to];
}
head2[u]=-;
if (ret) f[u]=Min(f[u],ret);
}
void Solve()
{
Get_Int(K);
for (int i=;i<=K;i++) Get_Int(H[i]);
sort(H+,H+K+,cmp);
tp=tot=; H[++tot]=H[];
for (int i=;i<=K;i++)
if (Lca(H[tot],H[i])!=H[tot]) H[++tot]=H[i];
cnt2=;
S[++tp]=;
for (int i=;i<=tot;i++)
{
LL u=H[i],f=Lca(u,S[tp]);
while (true)
{
if (dep[f]>=dep[S[tp-]])
{
Add2(f,S[tp--]);
if (S[tp]!=f) S[++tp]=f;
break;
}
Add2(S[tp-],S[tp]); tp--;
}
if (S[tp]!=u) S[++tp]=u;
}
while (--tp) Add2(S[tp],S[tp+]);
Dp();
Put_Int(f[]);
}
int main()
{
Get_Int(n);
memset(head,-,sizeof(head));cnt1=;
for (int i=;i<n;i++)
{
Get_Int(u),Get_Int(v),Get_Int(w);
Add(u,v,w),Add(v,u,w);
} father[]=; dep[]=; tot=; mn[]=Inf;
memset(vis,false,sizeof(vis));Dfs1();
memset(vis,false,sizeof(vis));Dfs2(,);
memset(head2,-,sizeof(head2));
Get_Int(m);
for (int i=;i<=m;i++) Solve();
return ;
}
C++
BZOJ 2286 树链剖分+DFS序+虚树+树形DP的更多相关文章
- BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】
一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...
- BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...
- [BZOJ - 2819] Nim 【树链剖分 / DFS序】
题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- 树链剖分&dfs序
树上问题 很多处理区间的问题(像是RMQ,区间修改).可以用线段树,树状数组,ST表这些数据结构来维护.但是如果将这些问题挪到了树上,就不能直接用这些数据结构来处理了.这时就用到了dfs序和树链剖分. ...
- 树链剖分||dfs序 各种题
1.[bzoj4034][HAOI2015]T2 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把 ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1352 Solved: 780[Submit][Stat ...
- BZOJ:2819 NIM(树链剖分||DFS序 &&NIM博弈)
著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略的.于是v ...
随机推荐
- [课程设计]Scrum 2.8 多鱼点餐系统开发进度(下单一览页面-菜式一览功能的最终实现)
Scrum 2.8 多鱼点餐系统开发进度 (下单一览页面-菜式一览功能的最终实现) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队 ...
- transient
“transient”——“瞬态”,先不说这个翻译是否恰当,这个变量关键字一直不曾使用,简单的说就是被瞬态定义的变量不可序列号.或者这么给他换个名字——“不可序列化状态”.打个比方,如果一个用户有一些 ...
- codeforces VK cup 2016-round 1 D.Bear and Contribution
题意大概就是有n个数字,要使至少有k个相同,可以花费b使一个数+5,可以花费c使一个数+1,求最小花费. 要对齐的数肯定是在[v,v+4]之间,所以分别枚举模为0~4的情况就可以了. 排序一下,然后化 ...
- python(九)re模块
python中re模块提供了正则表达式相关操作. 1. 字符串匹配: . 匹配除换行符以外的任意字符 \w 匹配字符或数字或下划线或汉字 \s 匹配任意空白字符 \d 匹配数字 \b 匹配单词 ...
- Hadoop安装指引
pre.ctl { font-family: "Liberation Mono", monospace } p { margin-bottom: 0.25cm; line-heig ...
- Windows Store Apps, Error: The certificate specified has expired.(转)
Windows Store Apps, Error: The certificate specified has expired. 0 comments|Posted on October 7th, ...
- Apache Solr 访问权限控制
Current state of affairs SSL support was added in version 4.2 (SolrCloud v4.7). Protection of Zookee ...
- MySQL 5.6 双机热备
目录: 1.说明 2.数据手工同步 3.修改主数据库配置文件 4.修改从数据库配置文件 5.主数据库添加备份用户 6.从数据库设置为Slave 7.验证 1.说明 1)数据库版本要高于5.1 2) ...
- "SQLServer无法打开用户默认数据库,登录失败,错误4064"的解决办法
"SQLServer无法打开用户默认数据库,登录失败,错误4064"的解决办法 1.检查登录密码 如果密码错误,修改数据库密码,用windows身份验证登录进去, (1)安全--登 ...
- PHP 小方法之 算生日
if (! function_exists ( 'diff_date' )) { function diff_date($date1, $date2){ $datestart = date ( 'Y- ...