f[x]=SUM{ min(f[y], z) } ( y是不重要的点)
建立虚树,然后dp
#include <bits/stdc++.h> using namespace std ; const int N=3e6,M=N,inf=1e9; #define int long long int mn[N],n; int stk[N],top ; int nxt[M],go[M],w[M],hd[N],all; int f[N]; vector<int> VT[N]; void add_(int x,int y,int z){ go[++all]=y,w[all]=z,nxt[all]=hd[x],hd[x]=all; } void V_ADD(int x,int y){ VT[x].push_back(y); VT[y].push_back(x); } int dep[N],F[N][21]; int dfn[N],pool ,B[N] ; int m,a[N] ; int cmp(int i,int j){ return dfn[i]<dfn[j] ; } void init(int x,int fa){ int i,y; dfn[x]=++pool; dep[x]=dep[fa]+1; F[x][0]=fa; for(i=0;i<=19;i++) F[x][i+1]=F[F[x][i]][i]; for(i=hd[x];i;i=nxt[i]){ y=go[i]; if(y==fa) continue; mn[y]=min(mn[x],w[i]); init(y,x); } } int lca(int x,int y){ int i; if(dep[x]<dep[y]) swap(x,y); for(i=19;i>=0;i--){ if(dep[F[x][i]]>=dep[y]) x=F[x][i]; } if(x==y) return x; for(i=19;i>=0;i--){ if(F[x][i]!=F[y][i]) x=F[x][i],y=F[y][i]; } return F[x][0]; } void dp(int x,int fa) { f[x] = 0; for(int i = 0;i < VT[x].size();i++) { int v = VT[x][i],w = mn[v]; if(v == fa) continue; dp(v,x); if(B[v]) { f[x] += w; } else { f[x] += min(f[v],w); } } VT[x].clear(); } void build() { sort(a + 1,a + 1 + m,cmp); top = 1; stk[top] = 1; for(int i = 1;i <= m;i++) { if(a[i] != 1) { int l = lca(a[i],stk[top]); if(l != stk[top]) { while(top >= 2 && dfn[l] < dfn[stk[top - 1]]) { V_ADD(stk[top - 1],stk[top]); top--; } if(dfn[l] > dfn[stk[top - 1]]) { V_ADD(l,stk[top]); stk[top] = l; } else { V_ADD(l,stk[top]); top--; } } stk[++top] = a[i]; } } for(int i = 1;i < top;i++) { V_ADD(stk[i],stk[i + 1]); } } signed main(){ int i,x,y,z; cin>>n; for(i=1;i<n;i++) cin>>x>>y>>z,add_(x,y,z),add_(y,x,z); memset(mn,127,sizeof mn); init(1,0); int tes; cin>>tes; while(tes--){ cin>>m; for(i=1;i<=m;i++){ cin>>a[i]; B[a[i]]=1; } build(); dp(1,0); cout<<f[1]<<'\n'; for(i=1;i<=m;i++) B[a[i]]=0; } }
标签:int,top,stk,SDOI2011,dfn,VT,消耗战,--,P2495 From: https://www.cnblogs.com/towboa/p/17228419.html