还是虚树的题目啊...

如果只有一个询问,我们这么考虑,可以设dp[x]为只删除x子树内和x到父亲的边,使得x这棵子树内的能源岛屿都与x的父亲不连通的最小花费。

这样如果x本身是能源岛屿,那么dp[x]=fe[x],否则dp[x]=min(fe[x],sum{dp[son[x]]})类似这样。(fe表示父亲边,fe[1]=inf)

那么有了多组询问我们就在虚树上搞这个,需要注意的是虚树上的一条父子边就对应着原树上一条父子链,而权值就是那个父子链的最小值。可以用倍增一起维护掉。

需要注意的是...要用long long啊

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
int inf=1000000000;
ll inf_ll=10000000000000000LL;
#define gc getchar()
int g_i()
{
int tmp=0; bool fu=0; char s;
while(s=gc,s!='-'&&(s<'0'||s>'9')) ;
if(s=='-') fu=1; else tmp=s-'0';
while(s=gc,s>='0'&&s<='9') tmp=tmp*10+s-'0';
if(fu) return -tmp; else return tmp;
}
#define gi g_i()
#define pob
#define pc(x) putchar(x)
namespace ib {char b[100];}
inline void pll(ll x)
{
if(x==0) {pc(48); return;}
if(x<0) {pc('-'); x=-x;}
char *s=ib::b;
while(x) *(++s)=x%10, x/=10;
while(s!=ib::b) pc((*(s--))+48);
}
#define SZ 1234567
#define D 20
#define _els ;else
//real tree
namespace rt
{
int n,fst[SZ],nxt[SZ],vb[SZ],vc[SZ],fa[SZ],dep[SZ],M=0,dfsn[SZ],C=0,sz[SZ],fe[SZ];
int up[SZ][D],mine[SZ][D];
void ad_de(int a,int b,int c) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b; vc[M]=c;}
void adde(int a,int b,int c) {ad_de(a,b,c); ad_de(b,a,c);}
void dfs(int p)
{
dfsn[p]=++C; sz[p]=1;
for(int e=fst[p];e;e=nxt[e])
{
int b=vb[e]; if(b==fa[p]) continue;
fa[b]=up[b][0]=p; fe[b]=vc[e]; mine[b][0]=fe[b];
dep[b]=dep[p]+1; dfs(b); sz[p]+=sz[b];
}
}
void build()
{
dfs(1);
for(int g=1;g<D;g++)
{
for(int i=1;i<=n;i++) mine[i][g]=inf;
}
for(int g=1;g<D;g++)
{
for(int i=1;i<=n;i++)
{
if(!up[i][g-1]) continue;
up[i][g]=up[up[i][g-1]][g-1];
mine[i][g]=min(mine[i][g-1],mine[up[i][g-1]][g-1]);
}
}
}
//jump up (x=fa[x]) until dep[x]=d
int jmp(int x,int d)
{
for(int i=D-1;i>=0;i--)
{
if(!up[x][i]||dep[up[x][i]]<d)_els x=up[x][i];
}
return x;
}
int gmin(int x,int d)
{
int minn=inf;
for(int i=D-1;i>=0;i--)
{
if(!up[x][i]||dep[up[x][i]]<d)_els minn=min(minn,mine[x][i]), x=up[x][i];
}
return minn;
}
int lca(int x,int y)
{
if(dep[x]>dep[y]) swap(x,y);
y=jmp(y,dep[x]);
if(x==y) return x;
for(int i=D-1;i>=0;i--)
{
if(up[x][i]!=up[y][i]) x=up[x][i], y=up[y][i];
}
return fa[x];
}
}
//virtual tree
namespace vt
{
#define f_ first
#define s_ second
typedef pair<int,int> pii;
//vs: points in vtree
int sn,ss[SZ],vn,vs[SZ],stn=0,st[SZ],vfa[SZ],fc[SZ],nc[SZ];
ll f[SZ],vfe[SZ];
bool saf[SZ];
bool cmp_dfsn(int a,int b) {return rt::dfsn[a]<rt::dfsn[b];}
ll dp(int x)
{
if(!saf[x]) return f[x]=vfe[x];
ll sum=0;
for(int c=fc[x];c;c=nc[c]) sum+=dp(c);
return f[x]=min((ll)vfe[x],sum);
}
void build()
{
vn=stn=0;
ss[++sn]=1;
sort(ss+1,ss+1+sn,cmp_dfsn);
for(int i=1;i<=sn;i++) vs[++vn]=ss[i], saf[ss[i]]=i==1;
for(int i=1;i<=sn;i++)
{
int x=ss[i];
if(!stn) {st[++stn]=x; vfa[x]=0; continue;}
int lca=rt::lca(x,st[stn]);
for(;rt::dep[st[stn]]>rt::dep[lca];--stn)
{
if(rt::dep[st[stn-1]]<=rt::dep[lca]) vfa[st[stn]]=lca;
}
if(st[stn]!=lca)
{
vs[++vn]=lca;
saf[lca]=1;
vfa[lca]=st[stn];
st[++stn]=lca;
}
vfa[x]=lca; st[++stn]=x;
}
sort(vs+1,vs+1+vn,cmp_dfsn);
for(int i=1;i<=vn;i++) fc[vs[i]]=0;
for(int i=1;i<=vn;i++)
{
int x=vs[i]; f[x]=inf_ll;
if(i>1) vfe[x]=rt::gmin(x,rt::dep[vfa[x]]);
else vfe[x]=inf_ll;
int f=vfa[x];
nc[x]=fc[f]; fc[f]=x;
}
pll(dp(1)); pc(10);
}
}
int main()
{
rt::n=gi;
for(int i=1;i<rt::n;i++)
{
int x=gi,y=gi,z=gi;
rt::adde(x,y,z);
}
rt::build();
int q=gi;
while(q--)
{
vt::sn=gi;
for(int i=1;i<=vt::sn;i++) vt::ss[i]=gi;
vt::build();
}
}

bzoj2286 消耗战的更多相关文章

  1. [Bzoj2286]消耗战(虚树+DP)

    Description 题目链接 Solution 在虚树上跑DP即可 Code #include <cstdio> #include <algorithm> #include ...

  2. [SDOI2011][bzoj2286] 消耗战 [虚树+dp]

    题面: 传送门 思路: 看到所有询问中的点数总和是十万级别的,就想到用虚树~\(≧▽≦)/~啦 首先,树形dp应该是很明显可以看出来的: 设dp[u]表示以u为根的子树(不包括u)中的宝藏岛全部切断的 ...

  3. [bzoj2286][Sdoi 2011]消耗战

    [bzoj2286]消耗战 标签: 虚树 DP 题目链接 题解 很容易找出\(O(mn)\)的做法. 只需要每次都dp一遍. 但是m和n是同阶的,所以这样肯定会T的. 注意到dp的时候有很多节点是不需 ...

  4. DP——由蒟蒻到神犇的进阶之路

    开始更新咯 DP专题[题目来源BZOJ] 一.树形DP 1.bzoj2286消耗战 题解:因为是树形结构,一个点与根节点不联通,删一条边即可, 于是我们就可以简化这棵树,把有用的信息建立一颗虚树,然后 ...

  5. 【BZOJ2286】消耗战(虚树,动态规划)

    [BZOJ2286]消耗战(虚树,动态规划) 题面 BZOJ Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总 ...

  6. [BZOJ2286][SDOI2011]消耗战(虚树DP)

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4998  Solved: 1867[Submit][Statu ...

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

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

  8. 虚树+【BZOJ2286】【SDOI2011】消耗战(虚树)(DP)

    先看一道题: [BZOJ2286][SDOI2011]消耗战 Description 在一场战争中,战场由n个岛屿和n−1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总 ...

  9. [BZOJ2286][Sdoi2011]消耗战(虚树上DP)

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6457  Solved: 2533[Submit][Statu ...

随机推荐

  1. 如何获取应用宝APP ID

    二百二维码支持绑定应用宝ID后,android 扫码下载后,微信直接下载APP,不打开应用宝页面,非常方便APP进行推广 那如何获取应用宝APP ID呢, 请参考下面的教程    一, 打开http: ...

  2. sqlite之WAL模式

    链接 概述 在3.7.0以后,WAL(Write-Ahead Log)模式可以使用,是另一种实现事务原子性的方法. WAL的优点 在大多数情况下更快 并行性更高.因为读操作和写操作可以并行. 文件IO ...

  3. sqlite学习1

    Architecture  就像编译器一样,结构分为前端.虚拟机.后端 性能和限制(limitations) 使用B树来做indexes,用B+树来做table.和其他数据库一样 由于不需要鉴权.网 ...

  4. 【读书笔记】iOS网络-使用Bonjour实现自组织网络

    Bonjour就是这样一种技术:设备可以通过它轻松探测并连接到相同网络中的其他设备,整个过程只需要很少的用户参与或是根本就不需要用户参与.该框架提供了众多适合于移动的使用场景,如基于网络的游戏,设备间 ...

  5. 设计模式 之 观察者(Observer)模式

    观察者(observer)模式定义了一对多的依赖关系,让多个观察者对象能够同时监听某一主题对象.这个主题对象中的状态发生改变时,就会通知所有的观察者对象. 观察者模式的结构图: 结构中各个部分的含义: ...

  6. 分页查询的SQL语句

    select * from(select row_number() over (ORDER BY Id DESC) cyqrownum,t.* from [Table_TY_Member] t ) v ...

  7. 关于JAVA中子类和父类的构造方法

    本篇文章总结了一些关于Java构造方法的常见问题. 为什么创建了一个子类对象会调用其父类的构造方法 如下代码示例: package simplejava; class Super { String s ...

  8. MongoDB ServerStatus返回信息

    ServerStatus返回信息 ServerStatus返回mongodb中很多信息 http://docs.mongodb.org/manual/reference/command/serverS ...

  9. Linux 性能优化工具包 sysstat 以及 sysstat 服务

    1. sysstat service 1.1. /etc/cron.d/sysstat Linux 下的性能分析,少不了要使用 sysstat 工具包中的命令.同时 sysstat 服务会自动每个10 ...

  10. JavaScript动态显示当前时间

    JavaScript动态显示当前时间: 2016年01月04日  时间:16:58:32  星期一 <span id="timejs"></span> &l ...