消耗战
在一场战争中,战场由 $n$ 个岛屿和 $n-1$ 个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为 $1$ 的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他 $k$ 个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到 $1$ 号岛屿上)。不过侦查部门还发现了这台机器只能够使用 $m$ 次,所以我们只需要把每次任务完成即可。
对于100%的数据, $2 \le n \le 250000,m \ge 1, \sum{k_i} \le 500000,1 \le k_i \le n-1 $
Solution
每次m个点,我们可以考虑建虚树。
割断一个点的代价为他到虚树上父亲的路径最小值。
然后dp就行。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #define ll long long 9 #define maxn 500005 10 using namespace std; 11 int n,m,num,head[maxn],tot,deep[maxn],f[maxn][22]; 12 int a[maxn],zh[maxn],top,dy[maxn],dfn[maxn],sc,ins[maxn],cnt,flag[maxn]; 13 ll dp[maxn],g[maxn]; 14 vector<int>G[maxn]; 15 struct node{ 16 int v,nex;ll w; 17 }e[maxn*2]; 18 void add(int t1,int t2,ll t3){ 19 e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot; 20 } 21 void dfs(int k,int fa,ll Min){ 22 dfn[k]=++sc;dy[sc]=k;g[k]=Min; 23 deep[k]=deep[fa]+1;f[k][0]=fa; 24 for(int i=head[k];i;i=e[i].nex){ 25 if(e[i].v==fa)continue; 26 dfs(e[i].v,k,min(Min,e[i].w)); 27 } 28 } 29 void lj(int t1,int t2){ 30 G[t1].push_back(t2);ins[++cnt]=t1; 31 } 32 int Lca(int u,int v){ 33 if(deep[u]<deep[v])swap(u,v); 34 for(int x=20;x>=0;x--)if(deep[f[u][x]]>=deep[v])u=f[u][x]; 35 for(int x=20;x>=0;x--)if(f[u][x]!=f[v][x])u=f[u][x],v=f[v][x]; 36 return u==v?u:f[u][0]; 37 } 38 void work(int k){ 39 ll sum=0; 40 for(int i=0;i<G[k].size();i++){ 41 work(G[k][i]); 42 sum+=dp[G[k][i]]; 43 } 44 if(flag[k])dp[k]=g[k],flag[k]=0; 45 else dp[k]=min(g[k],sum); 46 } 47 int main(){ 48 cin>>n; 49 for(int i=1,t1,t2;i<n;i++){ 50 ll t3; 51 scanf("%d%d%lld",&t1,&t2,&t3); 52 add(t1,t2,t3);add(t2,t1,t3); 53 } 54 dfs(1,0,1e15); 55 for(int j=1;j<=20;j++) 56 for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1]; 57 cin>>m; 58 while(m--){ 59 scanf("%d",&num); 60 for(int i=1,t;i<=num;i++){ 61 scanf("%d",&t);a[i]=dfn[t];flag[t]=1; 62 } 63 sort(a+1,a+num+1); 64 top=1;zh[top]=1;cnt=0; 65 for(int i=1;i<=num;i++){ 66 while(1){ 67 int l=Lca(dy[a[i]],zh[top]); 68 if(l==zh[top])break; 69 if(dfn[l]<dfn[zh[top-1]]){ 70 lj(zh[top-1],zh[top]);top--; 71 } 72 else if(dfn[l]==dfn[zh[top-1]]){ 73 lj(zh[top-1],zh[top]);top--;break; 74 } 75 else { 76 lj(l,zh[top]);zh[top]=l;break; 77 } 78 } 79 zh[++top]=dy[a[i]]; 80 } 81 while(top>1)lj(zh[top-1],zh[top]),top--; 82 work(1); 83 for(int i=1;i<=cnt;i++)G[ins[i]].clear(); 84 printf("%lld\n",dp[1]); 85 } 86 return 0; 87 }