[bzoj2286]消耗战

标签: 虚树 DP


题目链接

题解

很容易找出\(O(mn)\)的做法。

只需要每次都dp一遍。

但是m和n是同阶的,所以这样肯定会T的。

注意到dp的时候有很多节点是不需要的,真正有用的只是被询问的那k个点和他们的lca。

所以对于每次询问,我们只需要对于其中的点建一颗虚树。

然后在虚数上面dp。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
#define EREP_g(i,a) for(int i=start_g[(a)];i;i=g[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
} const int maxn=250020; struct node {
int v,next;ll w;
}; struct Node {
int v,next;
}; const ll inf=1ll<<60;
node e[maxn*2];Node g[maxn*2];
int cnt,start[maxn],cnt_g,start_g[maxn]; inline void addedge(int u,int v,ll w)
{
e[++cnt]=(node){v,start[u],w};
start[u]=cnt;
} inline void addedge_g(int u,int v)
{
g[++cnt_g]=(Node){v,start_g[u]};
start_g[u]=cnt_g;
} int n,dfn[maxn],times,deep[maxn],p[maxn][20];
ll dp[maxn],val[maxn]; inline void dfs(int u,int fa)
{
dfn[u]=++times;
deep[u]=deep[fa]+1;
p[u][0]=fa;
EREP(i,u)
{
int v=e[i].v;
if(v==fa)continue;
val[v]=min(val[u],e[i].w);
dfs(v,u);
} } inline void pre_LCA()
{
for(int j=1;(1<<j)<=n;j++)
REP(i,1,n)p[i][j]=p[p[i][j-1]][j-1];
} inline int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
DREP(i,19,0)if(deep[p[u][i]]>=deep[v])u=p[u][i];
if(u==v)return v;
DREP(i,19,0)if(p[u][i]!=p[v][i])u=p[u][i],v=p[v][i];
return p[u][0];
} inline void init()
{
n=read();
REP(i,1,n-1)
{
int u=read(),v=read();ll W;scanf("%lld",&W);
addedge(u,v,W);
addedge(v,u,W);
//w[v]=W;
}
val[1]=inf;
dfs(1,0);
pre_LCA();
} inline bool cmp(const int a,const int b)
{
return dfn[a]<dfn[b];
} inline void Dp(int u,int fa)
{
ll res=0;dp[u]=val[u];
EREP_g(i,u)
{
int v=g[i].v;
if(v==fa)continue;
Dp(v,u);
res+=dp[v];
}
start_g[u]=0;
if(res)dp[u]=min(res,dp[u]);
} int add[maxn],st[maxn];
inline void doing()
{
REP(i,1,read())
{
int top=0,tot=1;
int k=read();
REP(j,1,k)add[j]=read();
cnt_g=0;//REP(j,1,2*k)start_g[j]=0;
sort(add+1,add+k+1,cmp);
REP(i,2,k)if(lca(add[tot],add[i])!=add[tot])add[++tot]=add[i];
st[++top]=1;k=tot;
REP(j,1,k)
{
int u=st[top],v=add[j],Lca=lca(u,v);
if(u!=Lca)
{
//int x=st[--top];
while(dfn[st[--top]]>dfn[Lca])addedge_g(st[top],st[top+1]),addedge_g(st[top+1],st[top]); addedge_g(Lca,st[top+1]);addedge_g(st[top+1],Lca);
if(Lca!=st[top])st[++top]=Lca;
}
st[++top]=v;
}
--top;
while(top)addedge_g(st[top],st[top+1]),addedge_g(st[top+1],st[top]),top--;
Dp(1,0);
printf("%lld\n",dp[1]);
}
} int main()
{
init();
doing();
return 0;
}

[bzoj2286][Sdoi 2011]消耗战的更多相关文章

  1. [SDOI 2011]消耗战

    Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...

  2. 解题:SDOI 2011 消耗战

    题面 本身求答案是简单的树上DP,只需要求出根到每个点路径上的最小值,然后考虑割连父亲的边还是割所有儿子即可,但是每次都这样做一次显然不能通过,考虑优化 用虚树来优化:虚树是针对树上一些点建出来的一棵 ...

  3. 【BZOJ2286】[Sdoi2011]消耗战 虚树

    [BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...

  4. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  5. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  6. BZOJ 2243 SDOI 2011染色

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...

  7. [SDOI 2011]黑白棋

    Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...

  8. [SDOI 2011]染色

    Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...

  9. [SDOI 2011]计算器

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

随机推荐

  1. JVM核心之JVM运行和类加载全过程

    为什么研究类加载全过程? 有助于连接JVM运行过程 更深入了解java动态性(解热部署,动态加载),提高程序的灵活性 类加载机制 JVM把class文件加载到内存,并对数据进行校验.解析和初始化,最终 ...

  2. JS事件捕获和事件冒泡

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 19.0px; font: 14.0px "Helvetica Neue" ...

  3. 全新的软件项目,好的开始决定了成功一半!(需求&计划)

    刚看完“无问西东”,电影里说人总归还是要留下些足迹(文字)的,那么赶紧跑图书馆来留下些文字. 最近去瑞士启动了一个新的项目,那么早上做项目,晚上总结留下了一张张思维导图来记录当时的感受, 手稿如下,字 ...

  4. 序列化和Json

    实现了python与python程序之间内存的交互 常用场景: 1 把内存的数据写到磁盘 2 socket只能传字符串,二进制,通过序列化 ============================== ...

  5. arduino与DS1302时钟调试失败的分析

    前两天测试了时钟模块,但是,一直失败,能读取时间,但是设置不了时间,所以.这次我查了很多资料,发现好像是信号线的问题,线太长,数据收到干扰, 资料如下http://www.51hei.com/bbs/ ...

  6. 第二章 在HTML中使用JS

    script 标签 属性 src   : 可选 包含要执行的外部文件 type : 表示编写代码使用的脚本语言的内容类型(MINI类型) text/javascript async: 可选 只对外部脚 ...

  7. Hi,WeTest限免开放Android Oreo云真机,Android 8.1可开测!

    2017年末,谷歌在印度正式发布 Android Oreo 8.1,向实现"为所有人打造由 AI 驱动的全覆盖移动平台"这一愿景迈进.Android 8.1在引入对 Android ...

  8. MyEclipse中导出javadoc文档

    1.选中要生成文档的类或者项目→File→Export→Java→Javadoc. 2.在Javadoc command中选择JDK下对应的javadoc.exe:Select types for w ...

  9. javacript 组合使用构造函数模式和原型模式

    构造函数模式创建对象 基本方法 function Person(name,age){ this.name=name; this.age=age; this.sayName=function(){ al ...

  10. TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析[转]

    最近项目需要做单机100万长连接与高并发的服务器,我们开发完服务器以后,通过自己搭的高速压测框架压测服务端的时候,发生了奇怪的现象,就是服务端莫名其妙的少接收了连接,造成了数据包的丢失,通过网上查资料 ...