zoukankan      html  css  js  c++  java
  • bzoj 3611: [Heoi2014]大工程 虚树

    题目:

    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
    现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
    现在对于每个计划,我们想知道:
    1.这些新通道的代价和
    2.这些新通道中代价最小的是多少
    3.这些新通道中代价最大的是多少

    题解:

    这道题貌似是虚树的板子题.
    为了这道题去学了学虚树.

    因为我们发现我们只用在意两端都在关键点上的路径.
    所以说实际上非关键点除了增加了一些路径的长度就没有其他的用处了.

    我们可以考虑在原本的树上构造出一个只包括关键点但是赋予一定边一定的边权的与原树等价的树.
    这就叫做虚树.
    但是我们不能做到只保留关键点,我们仍然需要保留所有关键点之间的lca和lca之间的lca

    对于虚树的构造方法有(O(nlongn))的,可以去看其他的讲解,这里不再叙述.

    随后我们在虚树上进行dp,考虑每一条边对答案的贡献即可.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 2100010;
    const int inf = 0x3f3f3f3f;
    ll f[maxn];int g[maxn][2];
    int ans0,ans1,num;
    bool col[maxn];
    int son[maxn],top[maxn],dep[maxn];
    int fa[maxn],dfn[maxn],dfs_clock;
    struct Graph{
    	struct Edge{
    		int to,next;
    	}G[maxn<<1];
    	int head[maxn],cnt;
    	void add(int u,int v){
    		G[++cnt].to = v;
    		G[cnt].next = head[u];
    		head[u] = cnt;
    	}
    	int siz[maxn];
    #define v G[i].to
    	void dfs(int u){
    		siz[u] = 1;
    		for(int i = head[u];i;i=G[i].next){
    			if(v == fa[u]) continue;
    			fa[v] = u;
    			dep[v] = dep[u] + 1;
    			dfs(v);
    			siz[u] += siz[v];
    			if(siz[son[u]] < siz[v]) son[u] = v;
    		}
    	}
    	void dfs(int u,int tp){
    		top[u] = tp;dfn[u] = ++ dfs_clock;
    		if(son[u]) dfs(son[u],tp);
    		for(int i = head[u];i;i=G[i].next){
    			if(v == fa[u] || v == son[u]) continue;
    			dfs(v,v);
    		}
    	}
    	void dp(int u,int fa){
    		if(col[u]) siz[u] = 1;
    		else siz[u] = 0;
    		f[u] = 0;g[u][0] = inf;g[u][1] = 0;
    		for(int i = head[u];i;i=G[i].next){
    			if(v == fa) continue;
    			dp(v,u);siz[u] += siz[v];
    			int d = dep[v] - dep[u];
    			f[u] += f[v] + 1LL*d*siz[v]*(num - siz[v]);
    			ans0 = min(ans0,g[u][0] + d + g[v][0]);
    			ans1 = max(ans1,g[u][1] + d + g[v][1]);
    			g[u][0] = min(g[u][0],d + g[v][0]);
    			g[u][1] = max(g[u][1],d + g[v][1]);
    		}
    		if(col[u]){
    			ans0 = min(ans0,g[u][0]);
    			ans1 = max(ans1,g[u][1]);
    			g[u][0] = 0;
    		}
    		head[u] = 0;
    		return ;
    	}
    #undef v
    
    }pic1,pic2;
    inline int lca(int u,int v){
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		u = fa[top[u]];
    	}return dep[u] < dep[v] ? u : v;
    }
    int sta[maxn],a[maxn];
    inline bool cmp(const int &i,const int &j){
    	return dfn[i] < dfn[j];
    }
    int main(){
    	int n;read(n);
    	for(int i=1,u,v;i<n;++i){
    		read(u);read(v);
    		pic1.add(u,v);
    		pic1.add(v,u);
    	}
    	pic1.dfs(1);pic1.dfs(1,1);
    	int q;read(q);
    	while(q--){
    		pic2.cnt = 0;
    		read(num);
    		for(int i=1;i<=num;++i){
    			read(a[i]);
    			col[a[i]] = true;
    		}
    		sort(a+1,a+num+1,cmp);
    		int top = 0;
    		for(int i=1;i<=num;++i){
    			if(top == 0) sta[++top] = a[i];
    			else{
    				int lc = lca(sta[top],a[i]);
    				while(dfn[sta[top]] > dfn[lc]){
    					if(dfn[sta[top-1]] <= dfn[lc]){
    						pic2.add(lc,sta[top]);
    						if(sta[--top] != lc)sta[++top] = lc;
    						break;
    					}
    					pic2.add(sta[top-1],sta[top]);
    					-- top;
    				}
    				sta[++top] = a[i];
    			}
    		}
    		while(top > 1) pic2.add(sta[top-1],sta[top]),top--;
    		ans0 = inf;ans1 = 0;
    		pic2.dp(sta[1],sta[1]);
    		printf("%lld %d %d
    ",f[sta[1]],ans0,ans1);
    		for(int i=1;i<=num;++i) col[a[i]] = false;
    	}
    	return 0;
    }
    
  • 相关阅读:
    k8s是什么
    jmeter性能测试的策略
    面试的灵魂拷问:你最大的缺点是什么?
    面试的灵魂拷问:你做过的最令你自豪的事情是什么?
    面试的灵魂拷问:你犯过的最大的失误是什么?
    5-django rest framework,搭建api,这是最重要的章节
    4-restfulapi的介绍,vue代码结构
    组合恒等式证明——「Zeilberger 老爷子的 T 恤上写了啥?」
    「NOI2020」 美食家 【矩阵快速幂】
    [CEOI2014] The Wall【最短路】
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6592613.html
Copyright © 2011-2022 走看看