• BZOJ 2286 树链剖分+DFS序+虚树+树形DP


    第一次学习虚树,就是把无关的点去掉。S里维护一条链即可。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #define LL long long
      6 using namespace std;
      7 const LL Maxm=501000;
      8 const LL Maxn=250100;
      9 const LL Inf=1e60;
     10 struct Node {LL to,next,w;}edge[Maxm],edge2[Maxm];
     11 LL head[Maxn],head2[Maxn],dep[Maxn],H[Maxn],mark[Maxn],size[Maxn];
     12 LL top[Maxn],father[Maxn],f[Maxn],S[Maxn],mn[Maxn];
     13 LL cnt1,cnt2,tot,n,u,v,w,tp,m,K;
     14 bool vis[Maxn];
     15 inline void Add(LL u,LL v,LL w)
     16 {edge[cnt1].to=v;edge[cnt1].next=head[u];edge[cnt1].w=w;head[u]=cnt1++;
     17 edge[cnt1].to=u;edge[cnt1].next=head[v];edge[cnt1].w=w;head[v]=cnt1++;}
     18 inline void Add2(LL u,LL v)
     19 {if (u==v) return; edge2[cnt2].to=v;edge2[cnt2].next=head2[u];head2[u]=cnt2++;}
     20 inline LL Min(LL x,LL y) {return x>y?y:x;}
     21 inline void Get_Int(LL &x)
     22 {
     23     x=0;  char ch=getchar(); LL f=1;
     24     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
     25     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} x*=f;
     26 }
     27 inline void Put_Int(LL x)
     28 {
     29     char ch[20];  LL top=0;
     30     if (x==0) ch[++top]='0';
     31     while (x) ch[++top]=x%10+'0',x/=10;
     32     while (top) putchar(ch[top--]); putchar('
    ');
     33 }
     34 //================================================
     35 void Dfs1(LL u)
     36 {
     37     mark[u]=++tot;vis[u]=true; size[u]=1;
     38     for (LL i=head[u];i!=-1;i=edge[i].next)
     39         if (!vis[edge[i].to])
     40         {
     41             dep[edge[i].to]=dep[u]+1;
     42             father[edge[i].to]=u;
     43             mn[edge[i].to]=Min(mn[u],edge[i].w);
     44             Dfs1(edge[i].to);
     45             size[u]+=size[edge[i].to];
     46         }
     47 }
     48 void Dfs2(LL u,LL chain)
     49 {
     50     top[u]=chain; vis[u]=true; LL k=0;
     51     for (int i=head[u];i!=-1;i=edge[i].next)
     52         if (!vis[edge[i].to] && (size[edge[i].to]>size[k] || k==0)) k=edge[i].to;
     53     if (k==0) return;
     54     Dfs2(k,chain);
     55     for (int i=head[u];i!=-1;i=edge[i].next)
     56         if (!vis[edge[i].to] && i!=k) Dfs2(edge[i].to,edge[i].to);
     57 }
     58 inline LL Lca(LL u,LL v)
     59 {
     60     while (true)
     61     {
     62         if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
     63         if (dep[top[u]]>dep[top[v]]) u=father[top[u]]; 
     64         else v=father[top[v]];
     65     }
     66 }
     67 //=============================================================
     68 inline bool cmp(LL x,LL y) {return mark[x]<mark[y];}
     69 void Dp(LL u)
     70 {
     71 
     72     vis[u]=true; f[u]=mn[u]; LL ret=0;
     73     for (int i=head2[u];i!=-1;i=edge2[i].next)
     74     {
     75         Dp(edge2[i].to);
     76         ret+=f[edge2[i].to];
     77     }
     78     head2[u]=-1;
     79     if (ret) f[u]=Min(f[u],ret);
     80 }
     81 void Solve() 
     82 {
     83     Get_Int(K);
     84     for (int i=1;i<=K;i++) Get_Int(H[i]);
     85     sort(H+1,H+K+1,cmp);
     86     tp=tot=0; H[++tot]=H[1];
     87     for (int i=2;i<=K;i++) 
     88         if (Lca(H[tot],H[i])!=H[tot]) H[++tot]=H[i];
     89     cnt2=0;
     90     S[++tp]=1;
     91     for (int i=1;i<=tot;i++)
     92     {
     93         LL u=H[i],f=Lca(u,S[tp]);
     94         while (true)
     95         {
     96             if (dep[f]>=dep[S[tp-1]])
     97             {
     98                 Add2(f,S[tp--]);
     99                 if (S[tp]!=f) S[++tp]=f;
    100                 break;
    101             }
    102             Add2(S[tp-1],S[tp]); tp--;
    103         }
    104         if (S[tp]!=u) S[++tp]=u;
    105     }
    106     while (--tp) Add2(S[tp],S[tp+1]);
    107     Dp(1);
    108     Put_Int(f[1]);
    109 }
    110 int main()
    111 {
    112     Get_Int(n);
    113     memset(head,-1,sizeof(head));cnt1=0;
    114     for (int i=1;i<n;i++)
    115     {
    116         Get_Int(u),Get_Int(v),Get_Int(w);
    117         Add(u,v,w),Add(v,u,w);
    118     }
    119 
    120     father[1]=1; dep[1]=1; tot=0; mn[1]=Inf;
    121     memset(vis,false,sizeof(vis));Dfs1(1);
    122     memset(vis,false,sizeof(vis));Dfs2(1,1);
    123     memset(head2,-1,sizeof(head2));
    124     Get_Int(m);
    125     for (int i=1;i<=m;i++) Solve();
    126     return 0;
    127 }
    C++
  • 相关阅读:
    halconnorm_matrix求矩阵的范数
    Python中的super函数,你熟吗?
    送你5个MindSpore算子使用经验
    带你掌握如何使用CANN 算子ST测试工具msopst
    解析Stream foreach源码
    跟我学Python图像处理丨关于图像金字塔的图像向下取样和向上取样
    编译器优化:何为别名分析
    新消费时代,零售业的进与退?
    华为云宣布全面建设全球初创生态,3年内赋能10000家高潜初创企业
    一招教你如何高效批量导入与更新数据
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5517715.html
Copyright © 2020-2023  润新知