随笔 - 531  文章 - 0  评论 - 3  阅读 - 10215 

  f[x]=SUM{ min(f[y], z) }   ( y是不重要的点)

  

   建立虚树,然后dp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <bits/stdc++.h>
using namespace std ;
 const int N=3e6,M=N,inf=1e9;
 #define int long long
 int mn[N],n;
 int stk[N],top ;
 int nxt[M],go[M],w[M],hd[N],all;
  
 int f[N];
  
 vector<int> VT[N];
 void add_(int x,int y,int z){
     go[++all]=y,w[all]=z,nxt[all]=hd[x],hd[x]=all;
 }
 void V_ADD(int x,int y){
    VT[x].push_back(y);
    VT[y].push_back(x);
 }
 int dep[N],F[N][21];
 int dfn[N],pool ,B[N] ;
 int m,a[N] ;
 int cmp(int i,int j){
    return dfn[i]<dfn[j] ;
 }
   void init(int x,int fa){
     int i,y;
     dfn[x]=++pool;
     dep[x]=dep[fa]+1;
     F[x][0]=fa;
     for(i=0;i<=19;i++) F[x][i+1]=F[F[x][i]][i];
      
     for(i=hd[x];i;i=nxt[i]){
         y=go[i]; if(y==fa) continue;
         mn[y]=min(mn[x],w[i]);
         init(y,x);
     }
 }
 int lca(int x,int y){
     int i;
     if(dep[x]<dep[y]) swap(x,y);
      
     for(i=19;i>=0;i--){
         if(dep[F[x][i]]>=dep[y]) x=F[x][i];
     }
     if(x==y) return x;
      
     for(i=19;i>=0;i--){
         if(F[x][i]!=F[y][i]) x=F[x][i],y=F[y][i];
     }
     return F[x][0];
 }
  
 void dp(int x,int fa) {
    f[x] = 0;
    for(int i = 0;i < VT[x].size();i++) {
        int v = VT[x][i],w = mn[v];
        if(v == fa) continue;
        dp(v,x);
        if(B[v]) {
            f[x] += w;
        } else {
            f[x] += min(f[v],w);
        }
    }
    VT[x].clear();
}
 
 void build() {
    sort(a + 1,a + 1 + m,cmp);
    top = 1;
    stk[top] = 1;
     
    for(int i = 1;i <= m;i++) {
        if(a[i] != 1) {
            int l = lca(a[i],stk[top]);
            if(l != stk[top]) {
                while(top >= 2 && dfn[l] < dfn[stk[top - 1]]) {
                    V_ADD(stk[top - 1],stk[top]);
                    top--;
                }
                if(dfn[l] > dfn[stk[top - 1]]) {
                    V_ADD(l,stk[top]);
                    stk[top] = l;
                } else {
                    V_ADD(l,stk[top]);
                    top--;
                }
            }
            stk[++top] = a[i];
        }
    }
     
    for(int i = 1;i < top;i++) {
        V_ADD(stk[i],stk[i + 1]);
    }
}
 
 signed main(){
    int i,x,y,z;
    cin>>n;
    for(i=1;i<n;i++)
        cin>>x>>y>>z,add_(x,y,z),add_(y,x,z);
     
    memset(mn,127,sizeof mn);
    init(1,0);
     
    int tes;
    cin>>tes;
    while(tes--){
        cin>>m;
        for(i=1;i<=m;i++){
            cin>>a[i]; B[a[i]]=1;
        }
        build();
        dp(1,0);
        cout<<f[1]<<'\n';
        for(i=1;i<=m;i++) B[a[i]]=0;
    }
 }

 

posted on   towboat  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示