题链:
https://www.luogu.org/problemnew/show/P2495
题解:
虚树入门,树形dp
推荐博客:http://blog.csdn.net/lych_cys/article/details/50814948
代码:
#include<bits/stdc++.h> #define MAXN 250005 #define INFll 0x3f3f3f3f3f3f3f3fll using namespace std; int N,Q,M; bool mark[MAXN]; long long val[MAXN]; int mincut[MAXN],dfn[MAXN],deep[MAXN],fa[MAXN][19]; struct Edge{ int ent; int to[MAXN*2],val[MAXN*2],nxt[MAXN*2],head[MAXN]; Edge(){ent=2;} void Adde(int u,int v,int w){ to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++; } }E1,E2; bool cmp(int a,int b){return dfn[a]<dfn[b];} void read(int &x){ static int sign; static char ch; sign=1; x=0; ch=getchar(); for(;ch<'0'||'9'<ch;ch=getchar()) if(ch=='-') sign=-1; for(;'0'<=ch&&ch<='9';ch=getchar()) x=x*10+ch-'0'; if(sign==-1) x=-x; } void dfs(int u,int dep){ static int dnt; dfn[u]=++dnt; deep[u]=dep; for(int k=1;k<19;k++) fa[u][k]=fa[fa[u][k-1]][k-1]; for(int e=E1.head[u];e;e=E1.nxt[e]){ int v=E1.to[e]; if(v==fa[u][0]) continue; fa[v][0]=u; val[v]=min(val[u],1ll*E1.val[e]); dfs(v,dep+1); } } int LCA(int u,int v){ if(deep[u]>deep[v]) swap(u,v); for(int k=18;k>=0;k--) if(deep[fa[v][k]]>=deep[u]) v=fa[v][k]; if(u==v) return u; for(int k=18;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k]; return fa[u][0]; } long long dp(int u){ if(!E2.head[u]) return val[u]; long long tmp=0; for(int e=E2.head[u];e;e=E2.nxt[e]){ int v=E2.to[e]; tmp+=dp(v); } E2.head[u]=0; if(mark[u]) return val[u]; return min(tmp,val[u]); } void solve(){ static int a[MAXN*2],stk[MAXN*2],top,lca; read(M); E2.ent=2; top=0; for(int i=1;i<=M;i++) read(a[i]),mark[a[i]]=1; //虚树的构建------------------------------------ sort(a+1,a+M+1,cmp); stk[++top]=1; for(int i=1;i<=M;i++){ lca=LCA(stk[top],a[i]); if(lca!=stk[top]) while(1){ if(dfn[stk[top-1]]<=dfn[lca]){ E2.Adde(lca,stk[top],0),top--; if(stk[top]!=lca) stk[++top]=lca; break; } E2.Adde(stk[top-1],stk[top],0),top--; } if(stk[top]!=a[i]) stk[++top]=a[i]; } while(top>1) E2.Adde(stk[top-1],stk[top],0),top--; //----------------------------------------------- printf("%lld ",dp(1)); for(int i=1;i<=M;i++) mark[a[i]]=0; } int main(){ read(N); for(int i=1,a,b,c;i<N;i++){ read(a),read(b),read(c); E1.Adde(a,b,c); E1.Adde(b,a,c); } val[1]=INFll; dfs(1,1); read(Q); while(Q--) solve(); return 0; }