首页 > 其他分享 >感染 点分治优化建图

感染 点分治优化建图

时间:2024-08-23 15:37:25浏览次数:8  
标签:rt int 分治 id 建图 now 优化 mx dis

I 国有 \(n\) 个城市,有 \(n-1\) 条道路连接,并且所有的城市相互可达。城市因为自身的交通因素,人口因素,有一个传染力 \(r_i\) ,一旦这个城市爆发疫情,会迅速感染其他距离小于等于 \(r_i\) 的其他城市,并且造成连锁反应。

问一开始最少几个受到境外输入,会导致整个国家 \(n\) 个城市全部被感染。

为什么都写的这么复杂。首先就是建图 + Tarjan 强连通缩点后找入度为 \(0\) 个数。

重点就在这个优化建图。它十分地具有点分治的感觉。考虑点分治优化建图。

那么在固定算根为 \(u\) 的时候,直接 dfs 记录其子树中的点与其的距离 \(dis_v\)。那么 \(v_1\) 能向 \(v_2\) 连边即 \(dis_{v_1} + dis_{v_2} \leq r_{v_1}\)。转换成 \(dis_{v_2} \leq r_{v_1} - dis_{v_1}\),那么把 \(dis\) 从小到大排序,枚举 \(v_1\),满足的一定是一个前缀,用二分就能找到。那么就是一个前缀优化建图。新建虚点来表示前缀状态,然后长度差为 \(1\) 的前缀状态就长的连向短的,每一个前缀状态连向实际最末端的那个点。这样就可以枚举 \(v_1\) 然后连虚点了。然后用点分治优化整个过程。

最后一样的操作。注意跑 Tarjan 时只跑 \(1 \sim n\),因为你显然不能直接从虚点开始,虚点只是起到一个辅助连边的作用。然后只看被访问到的就好了。

namespace liuzimingc {
#define endl '\n'
#define int long long
const int N = 1e7 + 5, INF = 1e18;

int n, r[N], dfn[N], dep[N], cnt, low[N], id[N], a[N];
int siz[N], mx[N], scc_cnt, scc_id[N], dis[N], in[N], sum, tot, rt;
bool vis[N];
vector<pair<int, int>> e[N];
vector<int> e2[N];
stack<int> s;
vector<pair<int, int>> now;

void get_root(int u, int fa) {
	siz[u] = 1;
	mx[u] = 0;
	for (const auto &i : e[u]) {
		int v = i.first;
		if (v == fa || vis[v]) continue;
		get_root(v, u);
		siz[u] += siz[v];
		mx[u] = max(mx[u], siz[v]);
	}
	mx[u] = max(mx[u], sum - siz[u]);
	if (mx[u] < mx[rt]) rt = u;
}

void dfs(int u, int fa) {
	now.push_back(make_pair(dis[u], u));
	for (const auto &i : e[u]) {
		int v = i.first, w = i.second;
		if (v == fa || vis[v]) continue;
		dis[v] = dis[u] + w;
		dfs(v, u);
	}
}

void tree_divide(int u, int fa) {
	vis[u] = true;
	dis[u] = 0;
	now.clear();
	dfs(u, 0);
	sort(now.begin(), now.end());
	for (int i = 0; i < now.size(); i++) {
		a[i] = now[i].first;
		id[i] = ++tot;
		e2[id[i]].push_back(now[i].second);
		if (i) e2[id[i]].push_back(id[i - 1]);
	}
	for (int i = 0; i < now.size(); i++) {
		int d = r[now[i].second] - now[i].first;
		if (d < 0) continue;
		int x = upper_bound(a, a + now.size(), d) - a - 1;
		e2[now[i].second].push_back(id[x]);
	}
	for (const auto &i : e[u]) {
		int v = i.first;
		if (v == fa || vis[v]) continue;
		rt = 0;
		sum = siz[v];
		get_root(v, u);
		get_root(rt, 0);
		tree_divide(rt, 0);
	}
}

void tarjan(int u) {
	dfn[u] = low[u] = ++cnt;
	s.push(u);
	for (const int &v : e2[u]) {
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if (!scc_id[v]) low[u] = min(low[u], dfn[v]);
	}
	if (low[u] == dfn[u]) {
		scc_cnt++;
		int t;
		do {
			t = s.top(); s.pop();
			scc_id[t] = scc_cnt;
		} while (t != u);
	}
} // 为了避免太多 dfs 决定使用 tarjan 

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	mx[0] = INF;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> r[i];
	for (int i = 1; i < n; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		e[u].push_back(make_pair(v, w));
		e[v].push_back(make_pair(u, w));
	}
	sum = tot = n;
	rt = 0;
	get_root(1, 0);
	get_root(rt, 0);
	tree_divide(rt, 0);
	for (int i = 1; i <= n; i++)
		if (!dfn[i]) tarjan(i);
	for (int i = 1; i <= tot; i++)
		for (const int &j : e2[i]) {
			if (!scc_id[i] || !scc_id[j]) continue;
			if (scc_id[i] != scc_id[j]) in[scc_id[j]]++;
		}
	int ans = 0;
	for (int i = 1; i <= scc_cnt; i++)
		if (!in[i]) ans++;
	cout << ans << endl;
	return 0;
}
#undef int
} // namespace liuzimingc

标签:rt,int,分治,id,建图,now,优化,mx,dis
From: https://www.cnblogs.com/liuzimingc/p/18376079/inflection

相关文章

  • 【题解】Solution Set - NOIP2024集训Day14 CDQ分治
    【题解】SolutionSet-NOIP2024集训Day14CDQ分治https://www.becoder.com.cn/contest/5482「CF364E」EmptyRectangles*3000摆烂了。「SDOI2011」拦截导弹CDQ的例题,之前做过(现在试图自己再做出来。第二问只用在第一问里面记录每一次是从哪个\(j\)​转移过来的,以及......
  • CNN-BiLSTM-Attention(12种算法优化CNN-BiLSTM-Attention多输入单输出)
     12种算法优化CNN-BiLSTM-Attention模型预测的代码。其中Attention模型可以改为单头或者多头,在代码中就是改个数字而已。代码注释已写好如何更改。12种算法优化CNN-BiLSTM-Attention多特征输入单步预测代码获取戳此处代码获取戳此处代码获取戳此处主要功能为:采用12种......
  • VMD+降噪(鹈鹕优化VMD结合余弦相似度和改进小波阈值进行降噪)
     1.分解部分(POA-VMD)采用鹈鹕优化变分模态分解寻优对象:k α包含10种适应度函数可出适应度曲线图分解图频谱图三维分解图和α、K位置随迭代变化图适应度函数包括:1.综合评价指标2.包络熵3.包络谱峭度值4.幅值谱熵5.模糊熵6.皮尔逊系数7.峭度值8.样本熵9.排列熵10.信......
  • 博客园-awescnb插件-geek皮肤优化--公众号卡片
    简介博客园-awescnb插件-geek皮肤暂不支持配置展示公众号二维码,此文章目的使用手动注入方式自定义实现公众号卡片效果效果展示公众号卡片动态效果鼠标移入前为公众号指引页鼠标移入后显示公众号二维码切换动画为动态反转首页展示实现在博客日历元素blog-......
  • SQL 查询优化之 WHERE 和 LIMIT 使用索引详解
    奇怪的慢sql我们先来看2条sql第一条:第二条:表的索引及数据总情况: 索引:acct_id,create_time分别是单列索引,数据库总数据为500w。通过acct_id过滤出来的结果集在1w条左右。 查询结果:第一条要5.018s,第二条0.016s为什么会是这样的结果呢?第一,acct_id和create_time都有索引,不......
  • 根据EXPLAIN执行计划的Extra详细信息进行索引优化以及索引的使用原则
    一、根据EXPLAIN执行计划进行索引优化语法:Explain+SQL语句使用EXPLAIN关键字可以模拟优化器执行SQL语句,根据Extra信息,从而知道MySQL是如何理你的SQL语句的,分析你的查询语句或者表结构的性能瓶颈。Extra通常报的信息有以下几种:1.Usingindex查询......
  • 【鸿蒙学习】HarmonyOS应用开发者高级认证 - 应用性能优化一(界面层面)
    学完时间:2024年8月22日学完排名:第1801名一、介绍在开发HarmonyOS应用时,优化应用性能是至关重要的。通过/ArkTS高性能编程、减少丢帧卡顿、提升应用启动和响应速度可以有效提升用户体验。本文将介绍一些优化HarmonyOS应用性能的方法。一、ArkUI框架执行流程在使用A......
  • Scratch编程深度探索:解锁递归与分治算法的奥秘
    标题:Scratch编程深度探索:解锁递归与分治算法的奥秘在编程的世界里,递归和分治算法以其精妙的逻辑结构和解决问题的能力而著称。Scratch,这款专为儿童和初学者设计的图形化编程工具,是否能够支持实现这样复杂的逻辑呢?本文将深入探讨Scratch在实现递归和分治算法方面的能力,并提......
  • Little Bird(单调队列优化的DP)
    题目描述有一排\(n\)棵树,第\(i\)棵树的高度是\(d_i\)。有一只鸟要从第\(1\)棵树飞到第\(n\)棵树。如果鸟降落在第\(i\)棵树,那么它下一步可以降落到第\(i+1,i+2,\dots,i+k\)棵树之中的一棵。如果鸟降落到一棵不矮于当前树的树,那么它的劳累值会\(+1\),否则不会。求劳累值的最小值......
  • 单调栈和单调队列优化DP
    单调栈和单调队列优化DPluoguP1725琪露诺一道比较板的题明显是一个DP,则有\[{dp}_i=\max_{j=i-r}^{i-l}dp_j+a_i\]如果暴力则为\(O(n^2)\)但是发现\(\max_{j=i-r}^{i-l}dp_j\)就是单调队列所解决的问题,所以直接单调队列维护即可#include<bits/stdc++.h>#defineFAS......