【模板】虚树

似乎虚树的思想就是就是要把没用的点和边去掉,然后建一棵仅包含关键点的虚树。

过程中我们维护了一条“右链”。

其实除了规定的关键点,两两关键点的\(LCA\)也是必要的点。

struct VEDGE {
	int t, next;
} vedge[E];
int vedge_tot, vhead[V];
void add_vedge(int f,int t) {
	vedge[++vedge_tot].next = vhead[f];
	vedge[vedge_tot].t = t;
	vhead[f] = vedge_tot;
}

bool comp(const int &_x,const int &_y) {
	return dfn[_x] < dfn[_y];
}

int stk[V], h[V], k;
void VT_con() {
	std :: sort(h+1,h+k+1,comp);
	stk[++stk[0]] = 1;
	vhead[1] = 0;
	for(int i = 1;i <= k;++i) {
		if(h[i] == 1) 
			continue;
		int l = LCA(h[i],stk[stk[0]]);
		if(l != stk[stk[0]]) {
			while(dfn[l] < dfn[stk[stk[0]-1]]) {
				add_vedge(stk[stk[0]],stk[stk[0]-1]);
				add_vedge(stk[stk[0]-1],stk[stk[0]]);
				stk[0]--;
			}
			if(dfn[l] > dfn[stk[stk[0]-1]]) {
				vhead[l] = 0;
				add_vedge(l,stk[stk[0]]);
				add_vedge(stk[stk[0]],l);
				stk[stk[0]] = l;
			} else {
				add_vedge(l,stk[stk[0]]);
				add_vedge(stk[stk[0]],l);
				stk[0]--;
			}
		}
		vhead[h[i]] = 0;
		stk[++stk[0]] = h[i];
	}
	for(int i = 1;i < stk[0];++i) {
		add_vedge(stk[i],stk[i+1]);
		add_vedge(stk[i+1],stk[i]);
	}
}

小型练手题

\(\delta_i\)\(i\)\(1\)节点路上的最小权值,则有方程\(dp_u=\begin{cases}\min(\delta_u,\sum\limits_{u->v}dp_v)&u\text{不是关键节点}\\\delta_u&u\text{是关键节点}\end{cases}\)

code
#include <stdio.h>
#include <queue>
#include <math.h>
#include <bits/stl_algo.h>

const int V = 250010;
const int E = 500010;

struct EDGE {
	int t, next, w;
} edge[E];
int edge_tot, head[V];
void add_edge(int f,int t,int w) {
	edge[++edge_tot].next = head[f];
	edge[edge_tot].t = t;
	edge[edge_tot].w = w;
	head[f] = edge_tot;
}

int depth[V], parent[V][18], logup, dfn[V], time;
long long mn[V];
std :: queue<int> q;
void dfs(int u,int p) {
	dfn[u] = ++time;
	parent[u][0] = p;
	depth[u] = depth[p]+1;
	logup = log(depth[u])/log(2)+1;
	for(int i = 1;i <= logup;++i) 
		parent[u][i] = parent[parent[u][i-1]][i-1];
	for(int i = head[u];i;i = edge[i].next) {
		int v = edge[i].t;
		if(v == p) 
			continue;
		mn[v] = std :: min(mn[u],1ll*edge[i].w);
		dfs(v,u);
	}
}
int LCA(int u,int v) {
	if(depth[u] > depth[v]) 
		std :: swap(u,v);
	logup = log(depth[v])/log(2)+1;
	for(int i = logup;i >= 0;--i) 
		if(depth[parent[v][i]] >= depth[u]) 
			v = parent[v][i];
	if(u == v) return u;
	logup = log(depth[v])/log(2)+1;
	for(int i = logup;i >= 0;--i) 
		if(parent[u][i] != parent[v][i]) {
			u = parent[u][i];
			v = parent[v][i];
		}
	return parent[u][0];
}

struct VEDGE {
	int t, next;
} vedge[E];
int vedge_tot, vhead[V];
void add_vedge(int f,int t) {
	vedge[++vedge_tot].next = vhead[f];
	vedge[vedge_tot].t = t;
	vhead[f] = vedge_tot;
}

bool comp(const int &_x,const int &_y) {
	return dfn[_x] < dfn[_y];
}

int stk[V], h[V], k;
bool ck[V];
void VT_con() {
	std :: sort(h+1,h+k+1,comp);
	vedge_tot = 0;
	stk[stk[0] = 1] = 1;
	vhead[1] = 0;
	for(int i = 1;i <= k;++i) {
		if(h[i] == 1) 
			continue;
		int l = LCA(h[i],stk[stk[0]]);
		if(l != stk[stk[0]]) {
			while(dfn[l] < dfn[stk[stk[0]-1]]) {
				add_vedge(stk[stk[0]],stk[stk[0]-1]);
				add_vedge(stk[stk[0]-1],stk[stk[0]]);
				stk[0]--;
			}
			if(dfn[l] > dfn[stk[stk[0]-1]]) {
				vhead[l] = 0;
				add_vedge(l,stk[stk[0]]);
				add_vedge(stk[stk[0]],l);
				stk[stk[0]] = l;
			} else {
				add_vedge(l,stk[stk[0]]);
				add_vedge(stk[stk[0]],l);
				stk[0]--;
			}
		}
		vhead[h[i]] = 0;
		stk[++stk[0]] = h[i];
	}
	for(int i = 1;i < stk[0];++i) {
		add_vedge(stk[i],stk[i+1]);
		add_vedge(stk[i+1],stk[i]);
	}
}
long long vdfs(int u,int p) {
	long long temp = 0;
	for(int i = vhead[u];i;i = vedge[i].next) {
		int v = vedge[i].t;
		if(v == p) 
			continue;
		temp += vdfs(v,u);
	}
	temp = (ck[u] ? mn[u] : std :: min(1ll*mn[u],temp));
	ck[u] = false;
	return temp;
}

int n, m;
signed main() {
	scanf("%d",&n);
	for(int i = 1, a, b, c;i < n;++i) {
		scanf("%d %d %d\n",&a,&b,&c);
		add_edge(a,b,c);
		add_edge(b,a,c);
	}
	mn[1] = 99998244353;
	dfs(1,0);
	scanf("%d",&m);
	for(int i = 1;i <= m;++i) {
		scanf("%d",&k);
		for(int j = 1;j <= k;++j) {
			scanf("%d",&h[j]);
			ck[h[j]] = true;
		}
		VT_con();
		printf("%lld\n",vdfs(1,0));
	}
}
posted @ 2022-07-20 11:10  bikuhiku  阅读(23)  评论(0编辑  收藏  举报