BZOJ 2286: [Sdoi2011消耗战 [DP 虚树]
题意:
删除价值和最小的边使得$1$号点与$k$个关键点不连通
一个树形DP...但是询问多次,保证总的关键点数为$O(n)$
先说一下这个$DP$
$f[i]$表示子树$i$中的关键点与$1$不连通的最小价值
如果$i$是关键点则必须删除$i$到$1$的权值最小的边,否则$\sum f[child\ of\ i]$
学了一下虚树...找不到别的资料啊只有别人的$Blog$
试验了好多写法
貌似其中有好多带$Bug$的写法
最终定下了现在的版本应该是没大有问题的吧...明天再做两道虚树,有问题再来改
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=3e5+;
const ll INF=1e18;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,u,v,op,w;
int root;
struct Edge{
int v,ne,w;
}e[N<<];
int cnt,h[N];
inline void ins(int u,int v,int w){
cnt++;
e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
}
inline void ins2(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
int size[N],mx[N],top[N],dfn[N],dfc,deep[N],fa[N];
ll mn[N];
void dfs(int u){
size[u]++;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa[u]) continue;
deep[v]=deep[u]+; fa[v]=u;
mn[v]=min(mn[u],(ll)e[i].w);
dfs(v);
size[u]+=size[v];
if(size[v]>size[mx[u]]) mx[u]=v;
}
}
void dfs2(int u,int anc){
dfn[u]=++dfc;top[u]=anc;
if(mx[u]) dfs2(mx[u],anc);
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa[u] && e[i].v!=mx[u]) dfs2(e[i].v,e[i].v);
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return deep[x]<deep[y] ? x : y;
} int a[N],st[N];
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
ll f[N];
int key[N];
ll dp(int u){
ll t=;
for(int i=h[u];i;i=e[i].ne) t+=dp(e[i].v);
if(key[u]) f[u]=mn[u];
else f[u]=min(mn[u],t);
h[u]=;
return f[u];
}
void solve(){
cnt=;
n=read();
for(int i=;i<=n;i++) a[i]=read();
sort(a+,a++n,cmp);
//int p=0;
//a[++p]=a[1];
//for(int i=2;i<=n;i++)
// if(lca(a[p],a[i])!=a[p]) a[++p]=a[i];
//n=p;
for(int i=;i<=n;i++) key[a[i]]=;
int top=;
for(int i=;i<=n;i++){
if(!top){st[++top]=a[i];continue;}
int u=a[i],f=lca(u,st[top]);
while(dfn[f]<dfn[st[top]]){
if(dfn[f]>=dfn[st[top-]]){
ins2(f,st[top--]);
if(st[top]!=f) st[++top]=f;
break;
}else ins2(st[top-],st[top]),top--;
}
st[++top]=u;
}
while(top!=) ins2(st[top-],st[top]),top--;
dp(st[]);
for(int i=;i<=n;i++) key[a[i]]=;
printf("%lld\n",f[st[]]);
}
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<=n-;i++)
u=read(),v=read(),w=read(),ins(u,v,w);
mn[]=INF;dfs();dfs2(,);
Q=read();
memset(h,,sizeof(h));cnt=;
while(Q--) solve();
}
BZOJ 2286: [Sdoi2011消耗战 [DP 虚树]的更多相关文章
- bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...
- BZOJ 2286 [Sdoi2011]消耗战(虚树+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题目大意] 出一棵边权树,每次给出一些关键点,求最小边割集, 使得1点与各个关 ...
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- bzoj 2286: [Sdoi2011]消耗战 虚树+树dp
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4261 Solved: 1552 [Submit][Sta ...
- BZOJ 2286: [Sdoi2011]消耗战
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2082 Solved: 736[Submit][Status] ...
- [Bzoj2286][Sdoi2011]消耗战(虚树模板题附讲解)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4896 Solved: 1824[Submit][Statu ...
- [SDOI2011]消耗战(虚树)
洛古题面 题意:给定一棵树,割断每一条边都有代价,每次询问会给定一些点,求用最少的代价使所有给定点都和1号节点不连通 暴力\(DP\) 我们先考虑暴力怎么做 设\(dp[u]\)为以\(u\)为根的子 ...
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序
https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...
随机推荐
- RAID 详解
一.什么是RAID 磁盘阵列全名是『Redundant Arrays of Inexpensive Disks, RAID 』,英翻中的意思是:容错式廉价磁盘阵列. RAID 可以透过一个技术(软件或 ...
- SQL语句order by两个字段同时排序。
ORDER BY 后可加2个字段,用英文逗号隔开.理解:对两个字段都排序,并不是之排序其中的一个字段: f1用升序, f2降序,sql该这样写 ORDERBY f1, f2 DESC 也可以这样 ...
- Win7如何分享局域网并设置共享文件夹账户和密码
https://jingyan.baidu.com/article/ceb9fb10ddf6c08cad2ba017.html 在办公或者其他场所,我们需要分享自己的文件给朋友或者同事,但又不想同一局 ...
- 怎么使用linux命令重启服务器
一下的命令都可以重启Linux服务器: 1.shutdown -r now 2.reboot 3.startx
- Java数据结构和算法(十三)——哈希表
Hash表也称散列表,也有直接译作哈希表,Hash表是一种根据关键字值(key - value)而直接进行访问的数据结构.它基于数组,通过把关键字映射到数组的某个下标来加快查找速度,但是又和数组.链表 ...
- 认识Linux分区
前言 今年目标是熟练Linux系统与内核,没有老司机带只能自己慢慢参照鸟哥教程学习了.如果有老司机麻烦指导一下便捷路线,作为这方便的新手还是很乐意接受各位的意见.今天第一步就是熟悉安装Linux中分区 ...
- Centos 6.9安装配置MongoDB
注意:centos6上就不要装mongo3了,容易出错. 1. 下载 curl -O http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2 ...
- Oracle问题之ORA-01031权限不足
Oracle问题之ORA-01031权限不足 此时应该按照如下写: sqlplus /nolog conn / as sysdba shutdown immediate 本地以sysdba身份登录数据 ...
- java学习总结之文件操作--ByteArrayOutputStream的用法
ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区, 然后利用ByteArrayOutputStream和ByteArrayInputStream ...
- python3 第二十二章 - 函数式编程之Decorator(装饰器)
前面我们说了,在python中,一切皆对象.函数也是一个对象,而且函数对象可以被赋值给变量,通过变量也能调用该函数.如: def sayHello(name): print(name + ' hell ...