一种常数极大的虚树构建方法
  • 板块灌水区
  • 楼主mjsdnz
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/7/10 15:32
  • 上次更新2023/11/3 10:44:36
查看原帖
一种常数极大的虚树构建方法
828737
mjsdnz楼主2023/7/10 15:32

不吸氧过不去,吸氧跑5秒

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf=1e14+10;
const int N = 3e5 + 10;
int n;
vector<pair<int, int>>g[N];
int q;
int num;
int dfn[N], top[N], son[N], fa[N], dep[N], siz[N];
int minn[N];
struct cmp {
	bool operator() (int a, int b) const {
		return dfn[a] < dfn[b];
	}
};
void dfs1(int u, int fa) {
	::fa[u] = fa;
	siz[u] = 1;
	dfn[u] = ++num;
	son[u] = 0;
	for (auto e : g[u]) {
		int v = e.first;
		int val = e.second;
		if (v == fa) continue;
		minn[v]=min(val,minn[u]);
		dep[v] = dep[u] + val;
		dfs1(v, u);
		siz[u] += siz[v];
		if (siz[v] > siz[son[u]]) son[u] = v;
	}
}
void dfs2(int u, int fa, int top) {
	::top[u] = top;
	if (!son[u]) return;
	dfs2(son[u], u, top);
	for (auto e : g[u]) {
		int v = e.first;
		if (v == fa || v == son[u]) continue;
		dfs2(v, u, v);
	}
}
int lca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] >= dep[top[y]]) x = fa[top[x]];
		else y = fa[top[y]];
	}
	return dep[x] < dep[y] ? x : y;
}
namespace Vir{
	vector<pair<int,int>>g[N];
	set<int,cmp>s;
	set<int,cmp>all;
	queue<int>q;
	int dp[N];
	int m;
	int k;
	void build(){
		auto end=s.end();
		end--;
		for(auto i=s.begin();i!=end;i++){
			all.insert(*i);
			auto i_=++i;
			i--;
			all.insert(lca(*i,*i_));
		}
		all.insert(1);
		all.insert(*end);
		end=all.end();
		end--;
		for(auto i=all.begin();i!=end;i++){
			auto i_=++i;
			i--;
			int lc=lca(*i,*i_);
			g[lc].push_back({*i_,dep[*i_]-dep[lc]});
			g[*i_].push_back({lc,dep[*i_]-dep[lc]});
			q.push(lc);
			q.push(*i_);
		}
		
	}
	void init(){
		while(q.size()){
			int top=q.front();
			g[top].clear();
			q.pop();
		}
		s.clear();
		all.clear();
	}
	void find(int u,int fa){
		if(s.count(u)) dp[u]=minn[u];
		else {
			int sum=0;
			for(auto e:g[u]){
				int v=e.first;
				if(v==fa) continue;
				find(v,u);
				sum+=dp[v];
			}
			dp[u]=min(minn[u],sum);
		}
	}
	void work(){
		cin>>m;
		while(m--){
			init();
			cin>>k;
			while(k--){
				int aa;
				cin>>aa;
				s.insert(aa);
			}
			build();
			find(1,0);
			cout<<dp[1]<<endl;
		}
	}
}
signed main() {
	cin >> n;
	for (int i = 1; i < n; i++) {
		int u, v, val;
		cin >> u >> v >> val;
		g[u].push_back({v, val});
		g[v].push_back({u, val});
	}
	minn[1]=inf;
	dfs1(1,0);
	dfs2(1,0,1);
	using namespace Vir;
	work();
}
2023/7/10 15:32
加载中...