[bzoj2286][Sdoi 2011]消耗战
[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]消耗战的更多相关文章
- [SDOI 2011]消耗战
Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...
- 解题:SDOI 2011 消耗战
题面 本身求答案是简单的树上DP,只需要求出根到每个点路径上的最小值,然后考虑割连父亲的边还是割所有儿子即可,但是每次都这样做一次显然不能通过,考虑优化 用虚树来优化:虚树是针对树上一些点建出来的一棵 ...
- 【BZOJ2286】[Sdoi2011]消耗战 虚树
[BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...
- 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法
BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...
- BZOJ 2243 SDOI 2011染色
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...
- [SDOI 2011]黑白棋
Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...
- [SDOI 2011]染色
Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...
- [SDOI 2011]计算器
Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...
随机推荐
- Vue版本过渡变化
到了2.0以后,有哪些变化: 在每个组件模板,不在支持片段代码 之前: <template id="aaa"> <h3>我是组件</h3>< ...
- sudo :apt-get:command not found
在centos下用yum install xxx yum和apt-get的区别 一般来说著名的linux系统基本上分两大类: 1.RedHat系列:Redhat.Centos.Fedora等 2. ...
- 如何看apache的版本号
在服务器上输入httpd -v就可以看到 在服务器上运行apachectl -v命令即可 Server version: Apache/2.2.3 Server built: Feb 25 2012 ...
- Visio绘制用例图问题集锦
1.Visio画UML用例图没有include关系的解决方法 发现Visio UML用例里面找不到include关系,即"箭头"+"<<include> ...
- Powerdesigner+Execel
1.将Powerdesigner中的表(PDM)导入到execel中 Ctrl+Shift+X/tool->Execute commands ->Edit/Run script 粘贴如下v ...
- 转:Python之路,Day6 - 面向对象学习
这篇文章写的不错,转来收了 转自:http://www.cnblogs.com/alex3714/articles/5188179.html 本节内容: 面向对象编程介绍 为什么要用面向对象进 ...
- HX711初步处理记录
参考文档为极客工坊大神记录 http://www.geek-workshop.com/forum.php?mod=viewthread&tid=2315&highlight=hx711 ...
- Node.js之单利模式
在iOS中我们经常用到单利模式,这样就能够实现在多处共享同一数据,那么在Node.js中也存在这种模式. 我们知道,Node.js中模块的概念很重要,在写模块的接口的时候,只需要暴露出一个实例对象就能 ...
- Linux批量ping脚本
根据鸟哥的ping脚本,我重新修改了一下.用到的知识有:read.Linux按行读取.shell输出效果调整等 其中Linux按行读取文件比较重要,可参看文下链接 1 脚本功能: 批量ping当前路径 ...
- Android Studio打包APK时出现 is not translated in "en" (English) [MissingTranslation]
错误信息: Error:(16) Error: "baidutieba_client_inavailable" is not translated in "en" ...