开始更新咯
DP专题【题目来源BZOJ】
一、树形DP
1.bzoj2286消耗战
题解:因为是树形结构,一个点与根节点不联通,删一条边即可,
于是我们就可以简化这棵树,把有用的信息建立一颗虚树,然后开始DP即可
1 /* 2 思路: 3 */ 4 #include<algorithm> 5 #include<cstdio> 6 #include<cmath> 7 #include<iostream> 8 #include<cstring> 9 #define ll long long 10 #define inf 1e60 11 #define N 250005 12 #define M 550005 13 using namespace std; 14 int n,m,k,tot,top,tmp,ind; 15 int a[N]; 16 int now[N],pre[M],v[M],val[M]; 17 int now1[N],pre1[M],v1[M]; 18 int fa[N][22],deep[N],dfn[N],bin[22]; 19 int z[M],st[M]; 20 ll f[N],mx[N]; 21 int read() 22 { 23 int x=0,f=1; char ch; 24 while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') f=-1; 25 while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9'); 26 return x*f; 27 } 28 void ins(int a,int b,int c){ 29 ++tot; pre[tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c; 30 } 31 void insert(int a,int b){ 32 if (a==b) return; 33 ++tot; pre1[tot]=now1[a]; now1[a]=tot; v1[tot]=b; 34 } 35 void dfs(int x) 36 { 37 dfn[x]=++ind; 38 for (int i=1; bin[i]<=deep[x]; i++) 39 fa[x][i]=fa[fa[x][i-1]][i-1]; 40 for (int p=now[x]; p; p=pre[p]) 41 { 42 int son=v[p]; 43 if (son==fa[x][0]) continue; 44 deep[son]=deep[x]+1; 45 mx[son]=min(mx[x],(ll)val[p]); 46 fa[son][0]=x; 47 dfs(son); 48 } 49 } 50 int lca(int x,int y) 51 { 52 if(deep[x]<deep[y]) swap(x,y); 53 int t=deep[x]-deep[y]; 54 for (int i=0; bin[i]<=t; i++) 55 if (bin[i]&t) x=fa[x][i]; 56 for (int i=19; i>=0; i--) 57 if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 58 if (x==y) return x; return fa[x][0]; 59 } 60 void prework() 61 { 62 bin[0]=1; 63 for (int i=1; i<=21; i++) bin[i]=bin[i-1]*2; 64 tmp=0; mx[1]=inf; dfs(1); 65 } 66 bool cmp(int a,int b){return dfn[a]<dfn[b]; 67 } 68 void work() 69 { 70 sort(a+1,a+k+1,cmp); 71 top=tot=0; 72 z[1]=a[1]; top++; 73 for (int i=2; i<=k; i++) if (lca(z[top],a[i])!=z[top]) z[++top]=a[i]; 74 st[1]=1; tmp=1; 75 for (int i=1; i<=top; i++) 76 { 77 int now=z[i],f=lca(now,st[tmp]); 78 for (;;) 79 { 80 if (deep[f]>=deep[st[tmp-1]]) 81 { 82 insert(f,st[tmp--]); 83 if (st[tmp]!=f) st[++tmp]=f; 84 break; 85 } 86 insert(st[tmp-1],st[tmp]); tmp--; 87 } 88 if (st[tmp]!=now) st[++tmp]=now; 89 } 90 while (--tmp) insert(st[tmp],st[tmp+1]); 91 } 92 void dp(int x) 93 { 94 f[x]=mx[x]; ll sum=0; 95 for (int p=now1[x]; p; p=pre1[p]) 96 { 97 int son=v1[p]; dp(son); sum+=f[son]; 98 } 99 now1[x]=0; 100 if (sum==0) f[x]=mx[x]; else f[x]=min(f[x],sum); 101 } 102 void init() 103 { 104 n=read(); 105 for (int i=1; i<n; i++) 106 { 107 int u=read(),v=read(),val=read(); 108 ins(u,v,val); ins(v,u,val); 109 } 110 // m=read(); 111 prework(); 112 } 113 void solve() 114 { 115 m=read(); 116 for (int i=1; i<=m; i++) 117 { 118 k=read(); for (int j=1; j<=k; j++) a[j]=read(); work(); 119 dp(1); printf("%lld\n",f[1]); 120 } 121 } 122 int main() 123 { 124 init(); 125 solve(); 126 return 0; 127 }