首页 > 其他分享 >P2495 [SDOI2011] 消耗战

P2495 [SDOI2011] 消耗战

时间:2023-03-17 22:23:24浏览次数:46  
标签:int top stk SDOI2011 dfn VT 消耗战 -- P2495

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

  

   建立虚树,然后dp

 

#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;
 	}
 }
 
 

 

标签:int,top,stk,SDOI2011,dfn,VT,消耗战,--,P2495
From: https://www.cnblogs.com/towboa/p/17228419.html

相关文章

  • P2489 [SDOI2011]迷宫探险 题解
    题意简述:一个\(n\timesm\)的带墙体单入口多出口迷宫中有\(k\)个陷阱,陷阱分为有害或无害,有害会使人掉血,给出所有垃圾的有害与无害的所有排列组成的概率,给定人的血量,求......
  • 【SDOI2011】【BZOJ2242】计算器
    Description你被要求设计一个计算器完成以下三项任务:1、给定y、z、p,计算y^zmodp的值;2、给定y、z、p,计算满足xy≡z(modp)的最小非负整数;3、给定y、z......
  • P2484 [SDOI2011]打地鼠 题解
    P2484[SDOI2011]打地鼠题解目录P2484[SDOI2011]打地鼠题解题目分析思路代码题目P2484[SDOI2011]打地鼠题解分析锤子每次只能将每个洞里打掉一只地鼠,所以对于每......
  • 【XSY1976】【BZOJ2286】【SDOI2011】消耗战(虚树,dp)
    这题的dp思想还是比较容易想的,关键是如何保证时间复杂度,这时就用到了虚树的技巧。1.虚树是什么?(虚树的性质)不妨设现在询问给出了\(k\)个点,我们命名这些节点为关键节点。......
  • P2486 [SDOI2011]染色
    #include<iostream>#include<vector>usingnamespacestd;#defineintlonglongconstintN=1e5+1;intn,m;vector<int>to[N];intdep[N],fa......
  • P2491 [SDOI2011] 消防
    P2491SDOI2011消防算法竞赛进阶指南P374解法3(解法2为P1099树网的核),7FA4.3.2.5.3,LuoguP2491SDOI2011二分答案mid在树的直径上找离两端最远且距离小于mid......