第一次学习虚树,就是把无关的点去掉。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. [课程设计]Scrum 2.8 多鱼点餐系统开发进度(下单一览页面-菜式一览功能的最终实现)

    Scrum 2.8 多鱼点餐系统开发进度 (下单一览页面-菜式一览功能的最终实现) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队 ...

  2. transient

    “transient”——“瞬态”,先不说这个翻译是否恰当,这个变量关键字一直不曾使用,简单的说就是被瞬态定义的变量不可序列号.或者这么给他换个名字——“不可序列化状态”.打个比方,如果一个用户有一些 ...

  3. codeforces VK cup 2016-round 1 D.Bear and Contribution

    题意大概就是有n个数字,要使至少有k个相同,可以花费b使一个数+5,可以花费c使一个数+1,求最小花费. 要对齐的数肯定是在[v,v+4]之间,所以分别枚举模为0~4的情况就可以了. 排序一下,然后化 ...

  4. python(九)re模块

    python中re模块提供了正则表达式相关操作. 1. 字符串匹配: .    匹配除换行符以外的任意字符 \w 匹配字符或数字或下划线或汉字 \s  匹配任意空白字符 \d 匹配数字 \b 匹配单词 ...

  5. Hadoop安装指引

    pre.ctl { font-family: "Liberation Mono", monospace } p { margin-bottom: 0.25cm; line-heig ...

  6. Windows Store Apps, Error: The certificate specified has expired.(转)

    Windows Store Apps, Error: The certificate specified has expired. 0 comments|Posted on October 7th, ...

  7. Apache Solr 访问权限控制

    Current state of affairs SSL support was added in version 4.2 (SolrCloud v4.7). Protection of Zookee ...

  8. MySQL 5.6 双机热备

    目录: 1.说明 2.数据手工同步 3.修改主数据库配置文件 4.修改从数据库配置文件 5.主数据库添加备份用户 6.从数据库设置为Slave 7.验证 1.说明   1)数据库版本要高于5.1 2) ...

  9. "SQLServer无法打开用户默认数据库,登录失败,错误4064"的解决办法

    "SQLServer无法打开用户默认数据库,登录失败,错误4064"的解决办法 1.检查登录密码 如果密码错误,修改数据库密码,用windows身份验证登录进去, (1)安全--登 ...

  10. PHP 小方法之 算生日

    if (! function_exists ( 'diff_date' )) { function diff_date($date1, $date2){ $datestart = date ( 'Y- ...