[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 }
View Code

 

你可能感兴趣的:([bzoj2286] [Sdoi2011消耗战)