• 虚树 (模板)


    [SDOI2011] 消耗战 - 洛谷

    虚树,就是用来在图上dp时,避免无用的点太多影响时间的一种优化方式,它新建了一张图,从而减少无关点的遍历,在稀疏图上时能大大优化时间。

    具体做法就是,把所有关键点按dfs序排序,然后一条链一条链地遍历,其中会出现4中情况,参考大佬博客:题解 P2495 【[SDOI2011]消耗战】 - Rhodoks 的博客 - 洛谷博客 

    我们按照栈来遍历就正好符合由一条链跳到另一条链的过程,叶节点先出栈,根节点不变,再入新的链,按照不同情况连点,目的是保证这些关键点互相连接。

    参考代码:

    1. /*keep on going and never give up*/
    2. #include<bits/stdc++.h>
    3. using namespace std;
    4. #define int long long
    5. #define ll long long
    6. #define endl "\n"
    7. #define fast std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    8. const double E = exp(1);
    9. const double PI = acos(-1.0);
    10. const int mod=1e9+7;
    11. const int maxn=250010;
    12. struct node{
    13. int to,nxt,w;
    14. }e[maxn<<1];int tot,head[maxn];
    15. void add(int x,int y,int z){ e[++tot]={y,head[x],z};head[x]=tot;}
    16. int dep[maxn],fa[maxn],siz[maxn],son[maxn],top[maxn],mi[maxn];
    17. void dfs1(int x,int f){
    18. dep[x]=dep[f]+1;
    19. fa[x]=f;
    20. siz[x]=1;
    21. int mson=-1;
    22. for(int i=head[x];i;i=e[i].nxt){
    23. int v=e[i].to;
    24. if(f==v) continue;
    25. mi[v]=min(mi[x],e[i].w);
    26. dfs1(v,x);
    27. siz[x]+=siz[v];
    28. if(siz[v]>mson) son[x]=v,mson=siz[v];
    29. }
    30. }
    31. int dfn[maxn],id;
    32. void dfs2(int x,int t){
    33. top[x]=t;
    34. dfn[x]=++id;
    35. if(!son[x]) return ;
    36. dfs2(son[x],t);
    37. for(int i=head[x];i;i=e[i].nxt){
    38. int v=e[i].to;
    39. if(v==fa[x]||v==son[x]) continue;
    40. dfs2(v,v);
    41. }
    42. }
    43. int lca(int x,int y){
    44. while(top[x]!=top[y])dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
    45. return dep[x]<dep[y]?x:y;
    46. }
    47. int n,m,k,a[maxn],s[maxn],h;
    48. vector<int>g[maxn];
    49. void add_g(int x,int y){g[x].push_back(y);}
    50. void _insert(int x){
    51. if(h==1){ s[++h]=x;return;}
    52. int tep=lca(x,s[h]);
    53. if(tep==s[h])return ;//情况1
    54. while(h>1&&dfn[s[h-1]]>=dfn[tep])add_g(s[h-1],s[h]),h--;// 情况4化为2,3
    55. if(tep!=s[h])add_g(tep,s[h]),s[h]=tep;//情况2,3
    56. s[++h]=x;// 虚树建树
    57. }
    58. bool cmp(int x,int y){return dfn[x]<dfn[y];}
    59. int dp(int x,int fa){
    60. if(g[x].size()==0) return mi[x];
    61. int sum=0;
    62. for(auto y:g[x]) sum+=dp(y,x);
    63. g[x].clear();
    64. return min(sum,mi[x]);
    65. }
    66. signed main(){
    67. fast
    68. cin>>n;
    69. mi[1]=1e17;
    70. for(int i=1;i<n;i++){
    71. int x,y,z;
    72. cin>>x>>y>>z;
    73. add(x,y,z);add(y,x,z);
    74. }
    75. dfs1(1,0);dfs2(1,1);
    76. cin>>m;
    77. for(int i=1;i<=m;i++){
    78. int k;cin>>k;
    79. for(int j=1;j<=k;j++) cin>>a[j];
    80. sort(a+1,a+1+k,cmp);
    81. h=1;s[h]=1;
    82. for(int j=1;j<=k;j++)_insert(a[j]);
    83. while(h>0) add_g(s[h-1],s[h]),h--;
    84. cout<<dp(1,0)<<endl;
    85. }
    86. }

     

  • 相关阅读:
    GIL全局解释器锁与协程
    给你一个文件夹,统计其下面的文件数量,包括子文件夹下面的文件
    ARM Linux DIY(十三)Qt5 移植
    小黑星巴克冰镇浓缩leetcode之旅:21. 合并两个有序链表
    Java 实例:删除字符串中的一个字符和字符串替换
    pytest
    Springboot 3.0.0基于swagger3.0的根据实体类建表SQL语句(postgresql系类数据库)
    SpringBoot 如何使用 Ehcache 作为缓存
    内置函数部分
    C++贪心算法之乘船问题
  • 原文地址:https://blog.csdn.net/qq_62539009/article/details/125469467