[bzoj2286]消耗战
建虚树dp
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
typedef long long ll;
int anc[N][22];
ll mn[N];
const ll INF=1000000000000000000;
int n,m;
int num,dfn[N],dep[N];
int point[N];
bool cmp(const int a,const int b) {
return dfn[a]<dfn[b];
}
namespace Tr_all {
int hed[N],to[N];
ll val[N];
int cnt,nxt[N];
inline void adde(int u,int v,ll w) {
++cnt;
val[cnt]=w,to[cnt]=v,nxt[cnt]=hed[u];
hed[u]=cnt;
}
inline void dfs(int x,int pre) {
dfn[x]=++num;
dep[x]=dep[pre]+1;
if(x==1)mn[x]=INF;
anc[x][0]=pre;
for(int i=1; 1<<i<=n; i++) {
anc[x][i]=anc[anc[x][i-1]][i-1];
}
for(int i=hed[x]; i; i=nxt[i]) {
int v=to[i];
if(v==pre)continue;
mn[v]=min(mn[x],(ll)val[i]);
dfs(v,x);
}
}
int LCA(int x,int y) {
if(dep[x]<dep[y])swap(x,y);
for(int i=19; ~i; i--)if(dep[anc[x][i]]>=dep[y])
x=anc[x][i];
if(x==y)return x;
for(int i=19; ~i; i--)if(anc[x][i]!=anc[y][i])
x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
}
using Tr_all::LCA;
namespace Tr_cur {
int hed[N],to[N],nxt[N],cnt;
inline void adde(int u,int v) {
// cout<<u<<"-->"<<v<<endl;
++cnt;
to[cnt]=v,nxt[cnt]=hed[u];
hed[u]=cnt;
}
inline void clear() {
cnt=0;
}
inline ll DP(int x) {
ll val=0;
if(hed[x]==0)return mn[x];
for(int i=hed[x]; i; i=nxt[i]) {
int v=to[i];
val+=DP(v);
}
hed[x]=0;
return min(val,mn[x]);
}
}
using Tr_cur::DP;
int stk[N],top;
int main()
{
scanf("%d",&n);
for(int i=1; i<n; i++) {
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
Tr_all::adde(u,v,w);
Tr_all::adde(v,u,w);
}
Tr_all::dfs(1,0);
scanf("%d",&m);
while(m--) {
int tot;
scanf("%d",&tot);
for(int i=1; i<=tot; i++)
scanf("%d",&point[i]);
sort(point+1,point+tot+1,cmp);
stk[(top=1)]=1;
/*insert*/
for(int i=1; i<=tot; i++) {
int u=point[i];
int lca=LCA(u,stk[top]);
if(top==1) {
stk[++top]=u;
continue;
}
if(lca==stk[top])continue;
while(top>1&&dep[stk[top-1]]>dep[lca]) {
Tr_cur::adde(stk[top-1],stk[top]);
--top;
}
if(dep[stk[top]]>dep[lca]) {
Tr_cur::adde(lca,stk[top]);
top--;
}
if(dep[stk[top]]<dep[lca]) stk[++top]=lca;
stk[++top]=u;
}
while(--top) Tr_cur::adde(stk[top],stk[top+1]);
/**/
printf("%lld\n",DP(1));
Tr_cur::clear();
}
}