第一次学习虚树,就是把无关的点去掉。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的更多相关文章

  1. BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】

    一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...

  2. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

  3. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  4. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  5. 树链剖分&dfs序

    树上问题 很多处理区间的问题(像是RMQ,区间修改).可以用线段树,树状数组,ST表这些数据结构来维护.但是如果将这些问题挪到了树上,就不能直接用这些数据结构来处理了.这时就用到了dfs序和树链剖分. ...

  6. 树链剖分||dfs序 各种题

    1.[bzoj4034][HAOI2015]T2 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把 ...

  7. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  8. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  9. BZOJ:2819 NIM(树链剖分||DFS序 &&NIM博弈)

    著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略的.于是v ...

随机推荐

  1. python基础(内置函数+文件操作+lambda)

    一.内置函数 注:查看详细猛击这里 常用内置函数代码说明: # abs绝对值 # i = abs(-123) # print(i) #返回123,绝对值 # #all,循环参数,如果每个元素为真,那么 ...

  2. Linux phpbb论坛的安装(英文版)

    1:建立文件夹

  3. Flowplayer-Embedding

    SOURCE URL:https://flowplayer.org/docs/embedding.html Embedding Video embedding is an act where the ...

  4. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  5. 赤红血OL

    包含海量的PSD文档!!全PSD源文档-446M.你值得拥有! <ignore_js_op> <ignore_js_op> <ignore_js_op> <i ...

  6. C语言面试题(三)

    这篇主要聚焦在排序算法,包括常见的选择排序,插入排序,冒泡排序,快速排序.会对这四种排序的时间复杂度和空间复杂度进行探究. a.选择排序 int main(int argc,char **argv){ ...

  7. 让IE7 IE8支持CSS3 background-size属性

    简介 CSS3 新增的 background-size 是一个很有用的属性,用于定义背景图片的尺寸,有了这个属性,你就可以任意指定背景图片的大小.其中最常用的值应该要数 cover 了,该值能让背景图 ...

  8. [poj2155]Matrix(二维树状数组)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25004   Accepted: 9261 Descripti ...

  9. LTE Module User Documentation(翻译12)——X2切换(X2-based handover)

    LTE用户文档 (如有不当的地方,欢迎指正!) 18 X2-based handover   正如 3GPP 定义的,切换是改变用户服务小区的连接方式的过程.这一过程中涉及的两个基站通常称为源基站和目 ...

  10. 【转载】CSS position属性和实例应用

    目前几乎所有主流的浏览器都支持position属性("inherit"除外,"inherit"不支持所有包括IE8和之前版本IE浏览器,IE9.IE10还没测试 ...