P2495 [SDOI2011]消耗战

博客涉及虚树相关内容,但具体信息缺失。虚树是信息技术领域的概念,在相关算法等方面可能有应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#include<unordered_map>
#pragma GCC diagnostic error "-std=c++11"
//#pragma GCC optimize("-fdelete-null-pointer-checks,inline-functions-called-once,-funsafe-loop-optimizations,-fexpensive-optimizations,-foptimize-sibling-calls,-ftree-switch-conversion,-finline-small-functions,inline-small-functions,-frerun-cse-after-loop,-fhoist-adjacent-loads,-findirect-inlining,-freorder-functions,no-stack-protector,-fpartial-inlining,-fsched-interblock,-fcse-follow-jumps,-fcse-skip-blocks,-falign-functions,-fstrict-overflow,-fstrict-aliasing,-fschedule-insns2,-ftree-tail-merge,inline-functions,-fschedule-insns,-freorder-blocks,-fwhole-program,-funroll-loops,-fthread-jumps,-fcrossjumping,-fcaller-saves,-fdevirtualize,-falign-labels,-falign-loops,-falign-jumps,unroll-loops,-fsched-spec,-ffast-math,Ofast,inline,-fgcse,-fgcse-lm,-fipa-sra,-ftree-pre,-ftree-vrp,-fpeephole2",3)
#pragma GCC target("avx","sse2")
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 3e5 + 10;
int n, m, ki;
int w[N], dfn[N], rk[N], par[N][30], st = 0, dep[N];
ll mn[N];
struct edge {
	int  to, next, w;
}edge[N << 1];
int head[N], cnt;
vector<int>kp, grp[N];
bool cmp(int a, int b) {
	return dfn[a] < dfn[b];
}
void addedge(int u,int v,int w){
	edge[cnt].next = head[u];
	edge[cnt].to = v;
	edge[cnt].w = w;
	head[u] = cnt++;
}
void dfs1(int u, int f) {
	dfn[u] = ++st;
	rk[st] = u;
	par[u][0] = f;
	dep[u] = dep[f] + 1;
	upd(i, 1, 25) {
		par[u][i] = par[par[u][i - 1]][i - 1];
	}
	for (int i = head[u]; ~i; i = edge[i].next) {
		int v = edge[i].to; if (v == f)continue;
		mn[v] = min(1ll * edge[i].w, mn[u]);
		dfs1(v, u);
	}
}
int lca(int u, int v) {
	if (dep[u] < dep[v])swap(u, v);
	dwd(i, 24, 0) {
		if (dep[par[u][i]] >= dep[v]) {
			u = par[u][i];
		}
	}
	if (u == v)return u;
	dwd(i, 24, 0) {
		if (par[u][i] != par[v][i])
			u = par[u][i], v = par[v][i];
	}
	return par[u][0];
}
int stk[N];
int top = 0;
void addedge2(int u, int v) {
	grp[u].push_back(v);
	grp[v].push_back(u);
}
void insert(int x) {
	if (x == 1)return;
	int LCA = lca(x, stk[top]);
	if (LCA != stk[top]) {
		while (dfn[LCA] < dfn[stk[top - 1]]) {
			addedge2(stk[top - 1], stk[top]); top--;
		}
		if (dfn[LCA] != dfn[stk[top - 1]]) {
			addedge2(LCA, stk[top]);
			stk[top] = LCA;
		}
		else addedge2(LCA, stk[top--]);
	}
	stk[++top] = x;
}
bool q[N];
ll dp(int u,int f) {
	if (grp[u].size() == 1 && grp[u][0] == f) {
		grp[u].clear();
		q[u] = 0;
		return mn[u];
	}
	ll sum = 0;
	for (auto gg : grp[u]) {
		if (gg == f)continue;
		sum += dp(gg, u);
	}
	ll res;
	if (!q[u]) {
		res = min(mn[u], sum);
	}
	else res = mn[u];
	grp[u].clear();
	q[u] = 0;
	return res;
}
int main() {
	n = read(); 
	int u, v, w;
	upd(i, 0, n)head[i] = -1;
	upd(i, 1, n - 1) {
		u = read(), v = read(), w = read();
		addedge(u, v, w); addedge(v, u, w);
	}
	mn[1] = 1e18;
	dfs1(1, 0);
	m = read();
	while (m--) {
		kp.clear();
		ki = read();
		upd(i, 1, ki) {
			u = read(); kp.push_back(u);
			q[u] = 1;
		}
		sort(kp.begin(), kp.end(), cmp);
		stk[top = 1] = 1;
		for (auto pp : kp) {
			insert(pp);
		}
		while (top>1) {
			addedge2(stk[top], stk[top - 1]); top--;
		}
		printf("%lld\n", dp(1, 0));
	}
	return 0;
}
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值