zoukankan      html  css  js  c++  java
  • 虚树

    虚树就是将树上我们需要的关键信息,浓缩到一颗新的树上,这棵树上除了关键点还有任意一对关键点的(lca)的信息

    建立:

    这里介绍利用单调栈的做法,首先我们要明确一个目的,我们要用单调栈来维护一条虚树上的链。也就是一个栈里相邻的两个节点在虚树上也是相邻的,而且栈是从底部到栈首单调递增的(指的是栈中节点 DFS 序单调递增)

    我们每次遇到一个新的关键点,将他和栈顶求(lca),若(lca)不在栈顶,就弹栈,然后将(lca)和栈顶比较(dfn),重复这个操作直到栈顶的(dfn)序比(lca)小,然后将(lca)压进栈

    • tip:每次弹栈时就将新的栈顶和弹出去的点连边

    例题:

    • P2495 消耗战

    虚树模板题,我们每次将关键点建出一颗虚树,虚树上的边就是原树上该关键点到(lca)的路径上最小的一条边,然后直接DP

    (f[i])表示(i)不和子树内任何一个关键点联通的最小花费,转移就是:

    1. (v)是关键点
    f[u]=f[u]+w(u,v);
    
    1. (v)不是关键点
    f[u]=f[u]+min( w(u,v), f[v] );
    
    • 代码:
    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	const int maxn =  2.5e5+5;
    	
    	struct island
    	{
    		int u,dfn;
    	}k[maxn];
    	
    	bool cmp(island a,island b)
    	{
    		return a.dfn<b.dfn;
    	}
    	
    	struct edge
    	{
    		int to,val;
    		edge (int to,int val):to(to),val(val){}
    	};
    	
    	int kcnt=0,n,m,tim;
    	vector<edge> mp[maxn],vt[maxn];
    	int dfn[maxn],fa[maxn][25],dep[maxn];
    	long long g[maxn][25],d[maxn];
    	bool vis[maxn];
    	
    	void dfs(int u,int ff,long long w)
    	{
    		dep[u]=dep[ff]+1;
    		dfn[u]=++tim;
    		fa[u][0]=ff;
    		g[u][0]=w;
    		for(int i=0;i<(int)mp[u].size();i++)
    		{
    			int v=mp[u][i].to;
    			long long val=mp[u][i].val;
    			if(v==ff) continue;
    			dfs(v,u,val);
    		}
    	}
    	
    	int lca(int x,int y)
    	{
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=20;i>=0;i--)
    		{
    			if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    		}
    		if(x==y) return x;
    		for(int i=20;i>=0;i--)
    		{
    			if(fa[x][i]!=fa[y][i])
    			{
    				x=fa[x][i];
    				y=fa[y][i];
    			}
    		}
    		return fa[x][0];
    	}
    	
    	int query(int x,int y)
    	{
    		long long ans=0x3f3f3f;
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=20;i>=0;i--)
    		{
    			if(dep[fa[x][i]]>=dep[y])
    			{
    				ans=min(ans,g[x][i]);
    				x=fa[x][i];
    			}
    		}
    		return ans;
    	}
    	
    	void add(int u,int v)
    	{
    		int w=query(v,u);
    		vt[u].push_back(edge(v,w));
    		//printf("%d %d %d 
    ",u,v,w);
    	}
    	
    	void solve(int u)
    	{
    		for(int i=0;i<(int)vt[u].size();i++)
    		{
    			int v=vt[u][i].to;
    			int val=vt[u][i].val;
    			solve(v);
    			if(vis[v]) d[u]+=val;
    			else d[u]+=min(1ll*val,d[v]);
    			vis[v]=false;d[v]=0;
    		}
    		vt[u].clear();
    	}
    	
    	void work()
    	{
    		int a,b,c;
    		scanf("%d",&n);
    		for(int i=1;i<n;i++)
    		{
    			scanf("%d%d%d",&a,&b,&c);
    			mp[a].push_back(edge(b,c));
    			mp[b].push_back(edge(a,c));
    		}
    		dfs(1,0,0);
    		for(int i=1;i<=20;i++)
    		{
    			for(int j=1;j<=n;j++)
    			{
    				fa[j][i]=fa[fa[j][i-1]][i-1];
    				g[j][i]=min(g[j][i-1],g[fa[j][i-1]][i-1]);
    			}
    		}
    		scanf("%d",&m);
    		while(m--)
    		{
    			int cnt;
    			kcnt=0;
    			scanf("%d",&cnt);
    			for(int i=1;i<=cnt;i++)
    			{
    				scanf("%d",&k[++kcnt].u);
    				k[kcnt].dfn=dfn[k[kcnt].u];
    				vis[k[kcnt].u]=true;
    			}
    			stack<int> s;
    			sort(k+1,k+cnt+1,cmp);
    			s.push(1);
    			for(int i=1;i<=cnt;i++)
    			{
    				int u=k[i].u;
    				int l=lca(u,s.top());
    				while(s.top()!=l)
    				{
    					int tmp=s.top();s.pop();
    					if(dfn[s.top()]<dfn[l]) s.push(l);
    					add(s.top(),tmp);
    				}
    				s.push(u);
    			}
    			while(s.top()!=1)
    			{
    				int tmp=s.top();
    				s.pop();
    				add(s.top(),tmp);
    			}
    			solve(1);
    			printf("%lld
    ",d[1]);
    			d[1]=0;
    		}
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    [SCOI2007]降雨量
    [SCOI2005]骑士精神
    LUOGU P1342 请柬
    spfa的复活
    Luogu P2396 yyy loves Maths VII
    Luogu P2801 教主的魔法
    HEOI2012 采花
    USACO05DEC Cleaning Shifts
    CF438D The Child and Sequence
    Codechef October Challenge 2019 Div.2
  • 原文地址:https://www.cnblogs.com/youth518/p/13849386.html
Copyright © 2011-2022 走看看