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消耗战的主要内容,如果未能解决你的问题,请参考以下文章