[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.给 ...
随机推荐
- 在Intellij idea 2017中运行tomcat 8.5
前提:jdk,tomcat都已安装完,环境变量该配置的都配置了,tomcat localhost:xx 能登上去 首先新建web小项目 new project next 为项目命个名 finis ...
- [知了堂学习笔记]_牵线Eclipse和Tomcat第一篇 —— 配置Java环境变量&&安装eclipse
一.先给他们提供一个"浪漫的"环境,比如传说中的"鹊桥"--java环境变量.哈哈! 配置java环境变量. 下载jdk,根据自己电脑的版本和操作位数选择不同的 ...
- 转-HTTP POST GET SOAP本质区别详解
原文链接:HTTP POST GET SOAP本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认 ...
- Linux指令--性能监控和优化命令相关指令
原文出处:http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html.感谢作者无私分享 性能监控和优化命令相关指令有:top,free,v ...
- C#、Java之比较
很多人说C#是微软用来和Java抗衡的武器,因为二者在很大程度上有着惊人的相似,尽管如此,两者不同的地方也很多,所谓"于细微处见差异".那么两者的相似和区别都在什么地方呢?我们从今 ...
- Python类的__getitem__和__setitem__特殊方法
class testsetandget: kk = {}; def __getitem__(self, key): return self.kk[key]; ...
- JVM的内存分区
JVM的内存分区 这篇文章尝试讨论清楚JVM的内存分区情况. 1. JVM的内存和系统内存的关系 下图是对系统内存及JVM内存的大致描绘 对大多数操作系统,内存可以分为物理内存RAM及Sw ...
- JDK安装及Tomcat安装
JDK安装及Tomcat安装 JDK 解压JDK到常用盘符 D为例 Tomcat安装 将tomcat.zip解压到常用的根目录下,我这里以D盘为例.这样就算安装好了! 接下来开始配置环境变量,打开环境 ...
- JAVA并发编程学习笔记------基础构建模块
一.并发容器:ConcurrentHashMap:1.分段锁机制: 任意数量的读取线程可以并发的访问map,执行读取操作的线程和执行写入操作的线程可以并发的访问Map,并且一定数量的写入线程可以并发的 ...
- jQuery中的DOM操作------复制及包裹节点
1.复制节点: 如果单击<li>元素后需要再复制一个<li>元素,可以用clone()方法来完成: $(this).clone().appendTo("ul" ...