1. 程式人生 > >2018.09.25 bzoj2286: [Sdoi2011]消耗戰(虛樹+樹形dp)

2018.09.25 bzoj2286: [Sdoi2011]消耗戰(虛樹+樹形dp)

傳送門 又一道虛樹入門題。 這個dp更簡單啊。 直接記錄每個點到1的距離,簡單轉移就行了。 程式碼:

#include<bits/stdc++.h>
#define N 250005
#define ll long long
#define min(a,b) (a<b?a:b)
using namespace std;
inline ll read(){
	ll ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)
+(ch^48),ch=getchar(); return ans; } int n,q,m,First[N],first[N],cnt=0,dfn_cnt=0,tot=0,top=0,stk[N],dfn[N],dep[N],st[N][21],a[N]; ll dis[N],f[N]; bool col[N]; struct edge{int v,next,w;}e[N<<1]; inline void add(int u,int v,int w){e[++cnt].v=v,e[cnt].w=w,e[cnt].next=First[u],First[u]=cnt;} inline void
Add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline void dfs(int p){ dfn[p]=++dfn_cnt; for(int i=First[p];i;i=e[i].next){ int v=e[i].v; if(v==st[p][0])continue; st[v][0]=p,dep[v]=dep[p]+1,dis[v]=min(dis[p],e[i].w),dfs(v); } } inline int lca(int x,int y){ if(dep[x]<dep[
y])x^=y,y^=x,x^=y; for(int i=20;~i;--i)if(dep[x]-(1<<i)>=dep[y])x=st[x][i]; if(x==y)return x; for(int i=20;~i;--i)if(st[x][i]!=st[y][i])x=st[x][i],y=st[y][i]; return st[x][0]; } inline bool cmp(int x,int y){return dfn[x]<dfn[y];} inline void dfs1(int p){ f[p]=dis[p]; ll sum=0; for(int i=first[p];i;i=e[i].next){ int v=e[i].v; dfs1(v),sum+=f[v]; } if(sum&&!col[p])f[p]=min(f[p],sum); first[p]=0; } int main(){ n=read(),dis[1]=1e18; for(int i=1;i<n;++i){ int u=read(),v=read(),w=read(); add(u,v,w),add(v,u,w); } dfs(1),cnt=0; for(int j=1;j<=20;++j)for(int i=1;i<=n;++i)st[i][j]=st[st[i][j-1]][j-1]; q=read(); while(q--){ m=read(),tot=cnt=top=0; for(int i=1;i<=m;++i)a[i]=read(),col[a[i]]=true; sort(a+1,a+m+1,cmp); int t; for(int i=1;i<=m;++i){ if(!top){stk[++top]=a[i];continue;} t=lca(a[i],stk[top]); while(dep[stk[top]]>dep[t]){ if(dep[stk[top-1]]<=dep[t]){ Add(t,stk[top]),--top; if(stk[top]!=t)stk[++top]=t; break; } Add(stk[top-1],stk[top]),--top; } stk[++top]=a[i]; } while(top>1)Add(stk[top-1],stk[top]),--top; dfs1(stk[1]),printf("%lld\n",f[stk[1]]); for(int i=1;i<=m;++i)col[a[i]]=0; } return 0; }