bzoj 2286: [Sdoi2011消耗战

Posted xiyuedong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2286: [Sdoi2011消耗战相关的知识,希望对你有一定的参考价值。

  1 #include<cstdio>
  2 #include<iostream>
  3 #define M 1000009
  4 #define N 250009
  5 #define ll long long
  6 #define inf 1000000000000000000LL
  7 #include<algorithm>
  8 using namespace std;
  9 int n,head[N],next[M],u[M],cnt,fa[N][22],deep[N],m,h[N],dfn[N],TI,cnt1,zhan[N],tot,head1[N];
 10 int next1[M],u1[M],v[M];
 11 ll mn[N],f[N];
 12 void jia(int a1,int a2,int a3)
 13 {
 14     cnt++;
 15     next[cnt]=head[a1];
 16     head[a1]=cnt;
 17     u[cnt]=a2;
 18     v[cnt]=a3;
 19     return;
 20 }
 21 void jia2(int a1,int a2)
 22 {
 23     if(a1==a2)
 24       return;
 25     cnt1++;
 26     next1[cnt1]=head1[a1];
 27     head1[a1]=cnt1;
 28     u1[cnt1]=a2;
 29     return;
 30 }
 31 void dfs(int a1)
 32 {
 33     dfn[a1]=++TI;
 34     for(int i=1;(1<<i)<=deep[a1];i++)
 35       fa[a1][i]=fa[fa[a1][i-1]][i-1];
 36     for(int i=head[a1];i;i=next[i])
 37       if(u[i]!=fa[a1][0])
 38         {
 39             deep[u[i]]=deep[a1]+1;
 40             fa[u[i]][0]=a1;
 41             mn[u[i]]=min(mn[a1],(ll)v[i]);
 42             dfs(u[i]);
 43         }
 44 }
 45 bool cmp(int a1,int a2)
 46 {
 47     return dfn[a1]<dfn[a2];
 48 }
 49 int lca(int a1,int a2)
 50 {
 51     if(deep[a1]<deep[a2])
 52       swap(a1,a2);
 53     int a3=deep[a1]-deep[a2];
 54     for(int i=0;i<=20;i++)
 55       if(a3&(1<<i))
 56         a1=fa[a1][i];
 57     for(int i=20;i>=0;i--)
 58       if(fa[a1][i]!=fa[a2][i])
 59         {
 60             a1=fa[a1][i];
 61             a2=fa[a2][i];
 62         }
 63     if(a1==a2)
 64       return a1;
 65     return fa[a1][0];
 66 }
 67 void dp(int a1)
 68 {
 69     ll tmp=0;
 70     f[a1]=mn[a1];
 71     for(int i=head1[a1];i;i=next1[i])
 72       {
 73         dp(u1[i]);
 74         tmp+=f[u1[i]];
 75       }
 76     head1[a1]=0;
 77     if(tmp<f[a1]&&tmp)
 78       f[a1]=tmp;
 79     return;
 80 }
 81 void solve()
 82 {
 83     cnt1=0;
 84     scanf("%d",&h[0]);
 85     for(int i=1;i<=h[0];i++)
 86       scanf("%d",&h[i]);
 87     sort(h+1,h+h[0]+1,cmp);
 88     int tot=0;
 89     h[++tot]=h[1];
 90     for(int i=2;i<=h[0];i++)
 91         if(lca(h[tot],h[i])!=h[tot])h[++tot]=h[i];
 92     h[0]=tot;
 93     tot=0;
 94     zhan[++tot]=1;
 95     for(int i=1;i<=h[0];i++)
 96       {
 97         int f=lca(h[i],zhan[tot]);
 98         for(;1;)
 99           {
100             if(deep[f]>=deep[zhan[tot-1]])
101               {
102                   jia2(f,zhan[tot]);
103                   tot-=1;
104                   if(zhan[tot]!=f)
105                     {
106                             tot+=1;                   
107                             zhan[tot]=f;
108                      }
109                   break;
110               }
111             jia2(zhan[tot-1],zhan[tot]);
112             tot-=1;
113           }
114         if(h[i]!=zhan[tot])
115            {
116             tot+=1;
117               zhan[tot]=h[i];
118            }  
119       }
120     for(;tot>1;jia2(zhan[tot-1],zhan[tot]),tot--);
121     dp(1);
122     printf("%lld\n",f[1]);
123     return;
124 }
125 int main()
126 {
127     scanf("%d",&n);
128     for(int i=1;i<n;i++)
129       {
130         int a1,a2,a3;
131         scanf("%d%d%d",&a1,&a2,&a3);
132         jia(a1,a2,a3);
133         jia(a2,a1,a3);
134       }
135     mn[1]=inf;
136     dfs(1);
137     scanf("%d",&m);
138     for(int i=1;i<=m;i++)
139       solve();
140     return 0;
141 }

显然想到DP,然而DP超时,这个题是构建虚树,然后DP。

以上是关于bzoj 2286: [Sdoi2011消耗战的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2286: [Sdoi2011]消耗战

Bzoj2286--Sdoi2011消耗战

[BZOJ2286][Sdoi2011]消耗战

BZOJ2286[Sdoi2011]消耗战 虚树

bzoj 2286: [Sdoi2011]消耗战

bzoj2286 [Sdoi2011]消耗战