开始更新咯

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

相关文章:

  • 2021-06-12
  • 2021-12-23
  • 2021-11-02
  • 2021-11-15
  • 2021-10-27
  • 2021-10-08
  • 2021-10-11
猜你喜欢
  • 2022-02-08
  • 2021-12-01
  • 2021-08-22
  • 2021-11-14
  • 2021-10-01
  • 2021-06-12
  • 2021-08-24
相关资源
相似解决方案