在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。
第一行一个整数n,代表岛屿数量。
接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。
第n+1行,一个整数m,代表敌方机器能使用的次数。
接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。
1 #include<cstdio>
2 #include<cstring>
3 #include<vector>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7
8 typedef long long LL;
9 const int N = 250000+10;
10 const int D = 20;
11
12 struct Edge{ int u,v,w;
13 };
14 vector<Edge> es;
15 vector<int> g[N],G[N];
16 int fa[N][D],d[N],dfn[N],bin[D]; LL mx[N];
17 int n,m,dfsc;
18
19 void adde(int u,int v,int w) {
20 es.push_back((Edge){u,v,w});
21 int m=es.size(); g[u].push_back(m-1);
22 }
23 void adde2(int u,int v) {
24 if(u!=v) G[u].push_back(v); else return ;
25 printf("es(%d,%d)\n",u,v);
26 }
27 bool cmp(const int& lhs,const int& rhs) { return dfn[lhs]<dfn[rhs];
28 }
29
30 void dfs(int u) {
31 dfn[u]=++dfsc;
32 for(int i=0;i<g[u].size();i++) {
33 Edge e=es[g[u][i]]; int v=e.v;
34 if(v!=fa[u][0]) {
35 fa[v][0]=u;
36 for(int j=1;j<D;j++) fa[v][j]=fa[fa[v][j-1]][j-1];
37 d[v]=d[u]+1; mx[v]=min(mx[u],(LL)e.w);
38 dfs(v);
39 }
40 }
41 }
42 int LCA(int u,int v) {
43 if(d[v]>d[u]) swap(u,v);
44 for(int i=D-1;i>=0;i--)
45 if(d[fa[u][i]]>=d[v]) u=fa[u][i];
46 if(u==v) return u;
47 for(int i=D-1;i>=0;i--)
48 if(fa[u][i]!=fa[v][i]) u=fa[u][i] , v=fa[v][i];
49 return fa[u][0];
50 }
51 void read(int &x) {
52 char c=getchar(); while(!isdigit(c)) c=getchar();
53 x=0; while(isdigit(c)) x=x*10+c-‘0‘ , c=getchar();
54 }
55 LL f[N];
56 void dp(int u) {
57 LL tmp=0;
58 for(int i=0;i<G[u].size();i++) {
59 dp(G[u][i]);
60 tmp += f[G[u][i]];
61 }
62 G[u].clear(); //清空边表
63 f[u]=mx[u]; //f=mx 所以mx赋大值
64 if(tmp && tmp<f[u]) f[u]=tmp;
65 }
66 void solve() {
67 int top=0,tot=0,k;
68 static int st[N],h[N];
69 read(k);
70 for(int i=1;i<=k;i++) read(h[i]) ;
71 sort(h+1,h+k+1,cmp);
72 ///////////////////////////////////// 以下是一个十分机智的重新构图 from hzwer
73 h[++tot]=h[1];
74 for(int i=2;i<=k;i++)
75 if(LCA(h[tot],h[i])!=h[tot]) h[++tot]=h[i]; //虚树中不会出现询问点间的子孙后代关系
76 st[++top]=1;
77 for(int i=1;i<=tot;i++) {
78 int p=h[i],lca=LCA(p,st[top]);
79 for(;;) {
80 if(d[st[top-1]]<=d[lca]) {
81 adde2(lca,st[top--]);
82 if(st[top]!=lca) st[++top]=lca;
83 break;
84 }
85 adde2(st[top-1],st[top]); top--;
86 }
87 if(st[top]!=p) st[++top]=p;
88 }
89 while(--top) adde2(st[top],st[top+1]);
90 /////////////////////////////////////
91 dp(1);
92 printf("%lld\n",f[1]);
93 }
94
95 int main() {
96 read(n);
97 int u,v,w;
98 for(int i=0;i<n-1;i++) {
99 read(u),read(v),read(w);
100 adde(u,v,w) , adde(v,u,w);
101 }
102 mx[1]=1e18,d[1]=1; dfs(1); //d[1]=1
103 read(m);
104 while(m--) solve();
105 return 0;
106 }