[bzoj2286] [Sdoi2011消耗战
还是虚树恩。。模板都能打挂QAQ
先在原树上预处理出mndis[i],表示根节点到节点i 路径上边权的最小值(就是断开i与根的联系的最小花费)
建完虚树在虚树上跑树形DP。。f[i]表示断开 i 所在子树内所有有资源的节点 与根节点的联系的最小花费。
若i 节点没资源:f[i]=min( mndis[i] , sigma(f[j]) ),(j是i的儿子,且j所在子树内有有资源的节点)。
若i 节点有资源:f[i]=mndis[i]。。。
链剖大法好。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=250233; 8 const int inf=1002333333; 9 struct zs{ 10 int too,pre,dis; 11 }e[maxn<<1]; 12 struct zs1{ 13 int too,pre; 14 }e1[maxn<<1]; 15 int last[maxn],tot,last1[maxn],tot1; 16 int mndis[maxn],sz[maxn],st[maxn],top; 17 int dfn[maxn],dep[maxn],bel[maxn],fa[maxn],size[maxn],tim; 18 int have[maxn],poi[maxn]; 19 int i,j,k,K,n,m,a,b,c; 20 ll f[maxn]; 21 22 23 int ra;char rx; 24 inline int read(){ 25 rx=getchar(),ra=0; 26 while(rx<'0'||rx>'9')rx=getchar(); 27 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 28 } 29 30 31 inline void insert(int a,int b,int c){ 32 e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot; 33 e[++tot].too=a,e[tot].dis=c,e[tot].pre=last[b],last[b]=tot; 34 } 35 inline void ins(int a,int b){ 36 // printf(" %d-->%d\n",a,b); 37 e1[++tot1].too=b,e1[tot1].pre=last1[a],last1[a]=tot1; 38 } 39 40 41 void dfs(int x){ 42 dep[x]=dep[fa[x]]+1,size[x]=1; 43 for(int i=last[x];i;i=e[i].pre) 44 if(e[i].too!=fa[x]) 45 fa[e[i].too]=x, 46 mndis[e[i].too]=mndis[x]<e[i].dis?mndis[x]:e[i].dis, 47 dfs(e[i].too), 48 size[x]+=size[e[i].too]; 49 } 50 void dfs2(int x,int chain){ 51 int i,mxpos=0;bel[x]=chain,dfn[x]=++tim; 52 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&size[e[i].too]>=size[mxpos])mxpos=e[i].too; 53 if(!mxpos)return; 54 dfs2(mxpos,chain); 55 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mxpos)dfs2(e[i].too,e[i].too); 56 } 57 inline int getlca(int a,int b){ 58 if(dep[bel[a]]<dep[bel[a]])swap(a,b); 59 while(bel[a]!=bel[b]){ 60 a=fa[bel[a]]; 61 if(dep[bel[a]]<dep[bel[b]])swap(a,b); 62 } 63 return dep[a]<dep[b]?a:b; 64 } 65 66 67 inline void build(){ 68 register int i,lca; 69 st[top=1]=1; 70 for(i=1;i<=K;i++){ 71 lca=getlca(poi[i],st[top]); 72 while(dfn[st[top]]>dfn[lca]) 73 if(dfn[st[--top]]<=dfn[lca]){ 74 ins(lca,st[top+1]); 75 if(st[top]!=lca)st[++top]=lca; 76 }else ins(st[top],st[top+1]);//,puts(""); 77 st[++top]=poi[i]; 78 } 79 while(top>1)ins(st[top-1],st[top]),top--; 80 } 81 void query(int x){ 82 int i,to; 83 f[x]=sz[x]=0; 84 if(have[x]==m){f[x]=mndis[x],sz[x]=1;return;} 85 for(to=e1[i=last1[x]].too;i;to=e1[i=e1[i].pre].too){ 86 query(to); 87 if(sz[to])f[x]+=f[to],sz[x]+=sz[to]; 88 } 89 if(x!=1&&mndis[x]<f[x])f[x]=mndis[x]; 90 } 91 92 93 bool cmp(int a,int b){return dfn[a]<dfn[b];} 94 int main(){ 95 n=read(); 96 for(i=1;i<n;i++)a=read(),b=read(),c=read(),insert(a,b,c); 97 mndis[1]=inf,dfs(1),dfs2(1,1); 98 // for(i=1;i<=n;i++)printf(" %d\n",mndis[i]); 99 100 for(m=read();m;m--){ 101 K=read();for(i=1;i<=K;i++)have[poi[i]=read()]=m; 102 103 sort(poi+1,poi+1+K,cmp), 104 build(), 105 query(1), 106 printf("%lld\n",f[1]); 107 108 if(m>1){for(i=tot1;i;i--)last1[e1[i].too]=0;last1[1]=tot1=0;} 109 } 110 return 0; 111 }