[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.给 ...
随机推荐
- canvas实现倒计时效果示例(vue组件内编写)
前言: 此事例是在vue组件中,使用canvas实现倒计时动画的效果.其实,实现效果的逻辑跟vue没有关系,只要读懂canvas如何实现效果的这部分逻辑就可以了 canvas动画的原理:利用定时器,给 ...
- JavaScript var的作用域和提升
在ES6标准之前,var 作为唯一的声明变量关键字,本篇将着重介绍var的作用域和变量提升. 1. var Hoisting(变量提升) va rHoisting:使用var在函数或全局内任何地方声明 ...
- discuz数据库相关表
discuz 数据表对照cdb_access 用户权限表 cdb_adminactions 管理动作表cdb_admingroups ...
- 国内不谈java
今天晚上在整理电脑,不知道怎么回事,电脑里面放着一篇文章.打开一看写的挺好的,现在就贴出来,望共勉. 国内不谈java--会有千万人跳出来和你争嘴的.越是如此,我越是不忍心不说出来,越是不不忍心看 ...
- 搭建内网的NTP时间服务器
NTP时间服务器 标签: linux 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 1.简介 NTP(Network Time Protocol,网络时间协议) ...
- Part 4:表单和类视图--Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- nongsanli
之后的内容只能追加,不可以修改,删除. 1. mysql可以对字段进行MD5加密, 加密插入:INSERT INTO t_user(id,username,PASSWORD) VALUES('5 ...
- jQuery的属性,事件及操作
1.属性操作 1.1 基本属性操作 $("img").attr("src") 返回文档中所有图像的src属性值 $("img").attr( ...
- BZOJ 3731 3731: Gty的超级妹子树 [树上size分块 !]
传送门 题意:一棵树,询问子树中权值大于k的节点个数,修改点权值,插入新点,断开边:强制在线 该死该死该死!!!!!! MD我想早睡觉你知不知道 该死该死沙比提 断开边只会影响一个块,重构这个块就行了 ...
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...