首页 > 其他分享 >CF613D Kingdom and its Cities

CF613D Kingdom and its Cities

时间:2024-04-06 20:34:12浏览次数:31  
标签:Kingdom Cities anc int top ++ st fa CF613D

CF613D Kingdom and its Cities

虚树优化 dp

考虑无解的情况,若有两个重要城市相邻,那么无解。

对于有解的情况,朴素的如何求解最少占领的城市数?考虑从叶子节点开始向上贪心,假如当前 \(u\) 节点为关键点,那么对于它的子树 \(v\),若它的关键点能到 \(v\),就要和他断开。如果 \(u\) 节点不是关键点,那么如果出现两个以上的子树有关键点,他自己就要断开;否则不考虑断开。每次询问跑一次,那么总复杂度就是 \(O(nq)\)。考虑优化。

我们发现两两关键点之间的边是不重要的,除此之外,两两关键点的 \(lca\) 是重要的,它可以考虑到一个点断开多个点的情况。于是对每个询问建个虚树,就做完了。

复杂度 \(O(n\log n)\)。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back

typedef long long i64;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
int n, m, q, tot, ans;
std::vector<int> V[N];
int anc[N][20], dfn[N], dep[N], a[N];
void dfs(int u, int fa) {
	anc[u][0] = fa;
	dfn[u] = ++tot;
	dep[u] = dep[fa] + 1;
	for(int j = 1; j <= 19; j++) {
		anc[u][j] = anc[anc[u][j - 1]][j - 1];
	}
	for(auto v : V[u]) {
		if(v == fa) continue;
		dfs(v, u);
	}
}
int lca(int u, int v) {
	if(dep[u] < dep[v]) std::swap(u, v);
	for(int i = 19; i >= 0; i--) if(dep[anc[u][i]] >= dep[v]) u = anc[u][i];
	if(u == v) return u;
	for(int i = 19; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
	return anc[u][0];
}
int cnt;
int h[N];
struct node {
	int to, nxt;
} e[N << 1];
void add(int u, int v) {
	e[++cnt].to = v, e[cnt].nxt = h[u];
	h[u] = cnt;
}
bool cmp(int a, int b) {
	return dfn[a] < dfn[b];
}
int st[N], top;
int f[N], vis[N];
void build() {
	std::sort(a + 1, a + m + 1, cmp);
	for(int i = 1; i <= m; i++) {
		int rt = lca(a[i], st[top]);
		while(top && dep[st[top - 1]] >= dep[rt]) {
			add(st[top - 1], st[top]), top--;
		}
		if(st[top] != rt) {
			add(rt, st[top]), st[top] = rt;
		}
		st[++top] = a[i];
	}
	while(top > 1) {
		add(st[top - 1], st[top]);
		top--;
	}
}
void dp(int u, int fa) {
	int sum = 0;
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa) continue;
		dp(v, u);
		if(vis[v]) sum++;
	}
	if(vis[u]) { 
		for(int i = h[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			if(v == fa) continue;
			if(vis[v]) ans++;
		}
	} else {
		if(sum > 1) ans++;
		else if(sum == 1) vis[u] = 1;
	}
}
void clear(int u, int fa) {
	vis[u] = f[u] = 0;
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa) continue;
		clear(v, u);
	}
	h[u] = 0;
}
void Solve() {
	std::cin >> n;
	for(int i = 1; i < n; i++) {
		int u, v;
		std::cin >> u >> v;
		V[u].pb(v), V[v].pb(u);
	}
	dfs(1, 0);
	std::cin >> q;
	while(q--) {
		std::cin >> m;
		for(int i = 1; i <= m; i++) {
			std::cin >> a[i];
			vis[a[i]] = 1;
		}
		bool flg = 0;
		for(int i = 1; i <= m; i++) {
			if(vis[anc[a[i]][0]]) flg = 1; 
		}
		if(flg) {
			for(int i = 1; i <= m; i++) vis[a[i]] = 0;
			std::cout << "-1\n";
			continue;
		}
		build();
		dp(st[1], 0);
		std::cout << ans << "\n";
		f[st[1]] = 0;
		ans = cnt = top = 0;
		clear(st[1], 0);
	}
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	Solve();

	return 0;
}

标签:Kingdom,Cities,anc,int,top,++,st,fa,CF613D
From: https://www.cnblogs.com/FireRaku/p/18117887

相关文章

  • CF1922C Closest Cities 题解
    解题思路贪心,能走距离最短的城市就一定走。分别考虑\(x>y\)和\(x<y\)的情况,两种情况分别是从后向前转移和从前往后转移,分别预处理一个前缀和和后缀和即可。AC代码#include<stdio.h>#include<stdlib.h>#include<valarray>#defineN100005#definelllonglongintn......
  • CF685E Travelling Through the Snow Queen's Kingdom
    题意给定一张图,走出当前边的时间为\(i\)。\(q\)次询问,问\(s\)是否能在\(l\tor\)中走到\(t\)。Sol考虑将边从大到小插入图中。注意到当前边只能对起点造成贡献。复杂度\(O(n\times\max\{n,m\})\)Code#include<iostream>#include<algorithm>#include<cstd......
  • T399750 Cell kingdom(Hard) 题解
    LinkT399750Cellkingdom(Hard)Qustion第一天产生\(1\)个细胞,之后的每一天,一个细胞都会分裂成\(8\)个和自己一样的细胞,每个细胞在第三天都会自爆并且带走当天产生的\(6\)个细胞,求第\(x\)天有多少细胞Solution我们设\(F[i]\)表示第\(i\)天产生的新细胞个数那么可......
  • Ways China’s Cities Can Drive Equitable and Sustainable Urbanization
    Thefive-yearplanrepresentsanopportunitynotjusttoadvanceclimategoals,buttocreatebettercitiesasurbanizationcontinues.HerearefivewaysChina’sFive-YearPlancanhelpsteerthenationtowardachievingajusttransitionandgreenurbaniz......
  • 'ddlCities' has a SelectedValue which is invalid because it does not exist in th
    this.ddlCities.DataSource=GetAll_List();this.ddlCities.DataTextField="Name";this.ddlCities.DataValueField="Id";this.ddlCities.DataBind();错误:'ddlCities'hasaSelectedValuewhichisinvalidbecauseitdoe......
  • PAT 甲级【1013 Battle Over Cities】
    本题就是dfs.连通图个数-2;但是java慢,最后一个case超时importjava.io.*;importjava.util.HashSet;importjava.util.Set;publicclassMain{@SuppressWarnings("uncheck")publicstaticvoidmain(String[]args)throwsIOException{StreamToken......
  • CodeForces 1062F Upgrading Cities
    洛谷传送门CF传送门考虑一个子问题:求从某个点\(u\)能到达的点数。如果要精确地计算出来,最优解法只能是\(O(\frac{n^2}{w})\)的bitset。但是我们还没有利用到题目的性质,我们只需要判断一个点是否至多有一个点互不可达。考虑拓扑排序的过程,队列里面的点两两互不可达。维护......
  • CF613D 题解
    一、题目描述:给你一颗$n$个点的树,有$m$组询问。一个点如果被攻占,那么这个点就不能通行了。第$i$次询问给出$k_i$个关键点,关键点不能被攻占。求最少攻占多少个点可以使得关键点两两不连通。若不可能,输出$-1$。数据范围:$1\len,m\le1\times10^5......
  • IPQ6010 QCN9074|Unleashing the Power of Long-Range Transmission in IIoT, Smart C
    UnleashingthePowerofLong-RangeTransmissioninIIoT,SmartCities,andSmartPortswithIPQ6010QCN9074Intheever-evolvinglandscapeofwirelesscommunication,thepossibilitiesseemboundless.Astechnologysurgesforward,sodoesourabilitytobri......
  • CF1101F Trucks and Cities
    题目大意有\(n\)个城市坐落在一条数轴上,第\(i\)个城市位于位置\(a_i\)。城市之间有\(m\)辆卡车穿行。每辆卡车有四个参数:\(s_i\)为起点编号,\(f_i\)为终点编号,\(c_i\)表示每行驶\(1\)个单位长度需要消耗的油量,\(r_i\)表示可以在路途中加油的次数。当卡车到达一个城......