首页 > 其他分享 >P6037 Ryoku 的探索

P6037 Ryoku 的探索

时间:2024-04-17 20:55:19浏览次数:23  
标签:rt 遍历 环上 探索 int P6037 i64 Ryoku define

P6037 Ryoku 的探索

基环树

有两种思路:

  1. 将环上一条边断开,转化为树上问题
  2. 先考虑环上,再考虑环上每个点构成的子树。

考虑后者。首先基环树上深度遍历只会少走一条边,所以考虑哪条边没被走。可以发现,基环树上深度遍历完后没遍历的边一定在环上。那么如果起点在环上,没遍历的边一定是它在环上的两条边中美观度最小的那条。怎么理解呢?我们从起点,在环上走一定会选择一个方向,沿这个方向绕环一圈后没遍历的就是起点在环上所连的另一条边了。

考虑起点不在环上,那么我们遍历完不在环上的部分后就会走到环上,那么结果就和环上那点一样了。

先对所有边权求和,难点是找到环后记录环上答案(这里我用了栈序列记录从根到该节点的简单路径,然后找到环后直接遍历栈序列即可),最后以环上每个点覆盖其子树即可。

复杂度 \(O(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 = 1e6 + 10;
int n, cnt;
i64 ans, f[N];
struct node {
	int to, nxt;
	i64 w, p;
} e[N << 1];
int h[N];
void add(int u, int v, int w, int p) {
	e[++cnt].to = v;
	e[cnt].nxt = h[u];
	e[cnt].w = w, e[cnt].p = p;
	h[u] = cnt;
}
bool flg;
int top;
bool ins[N], vis[N];
pii st[N];
void dfs(int u, int fa, int num) {
	st[++top] = {u, num};
	ins[u] = 1;
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa) continue;
		if(ins[v] && !flg) {
			int h = 1;
			while(h <= top && st[h].fi != v) h++;
			for(int j = h; j <= top; j++) {
				vis[st[j].fi] = 1;
				int l = (j != h) ? st[j].se : i, r = (j != top) ? st[j + 1].se : i;
				if(e[l].p > e[r].p) f[st[j].fi] = e[r].w;
				else f[st[j].fi] = e[l].w;
			}
			flg = 1;
		}
		else if(!ins[v]) dfs(v, u, i);
	}
	top--; //注意出栈
}
void upd(int u, int fa, int rt) {
	f[u] = f[rt];
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa || vis[v]) continue;
		upd(v, u, rt);
	}
}
void Solve() {
	std::cin >> n;
	for(int i = 1; i <= n; i++) {
		int u, v, w, p;
		std::cin >> u >> v >> w >> p;
		add(u, v, w, p), add(v, u, w, p);
		ans += w;
	}
	dfs(1, 0, 0);
	for(int i = 1; i <= n; i++) {
		if(vis[i]) {
			upd(i, 0, i);
		}
	}
	for(int i = 1; i <= n; i++) {
		std::cout << ans - f[i] << "\n";
	}
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	Solve();

	return 0;
}

标签:rt,遍历,环上,探索,int,P6037,i64,Ryoku,define
From: https://www.cnblogs.com/FireRaku/p/18141768

相关文章

  • 深度解读《深度探索C++对象模型》之拷贝构造函数
    接下来我将持续更新“深度解读《深度探索C++对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文。写作不易,请有心人到我的公众号上点点赞支持一下,增加一下热度,也好让更多的人能看到,公众号里有完整的文章列表可供阅读。有以下三种情况,一个类对象的初始......
  • 深度解读《深度探索C++对象模型》之默认构造函数
    接下来我将持续更新“深度解读《深度探索C++对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,主动获得推文。提到默认构造函数,很多文章和书籍里提到:“在需要的时候编译器会自动生成一个默认构造函数”。那么关键的问题来了,到底是什么时候需要?是谁需要?比如下面的......
  • 深度探索:Secure Hash Algorithm(SHA)全景解析
    title:深度探索:SecureHashAlgorithm(SHA)全景解析date:2024/4/1518:33:17updated:2024/4/1518:33:17tags:SHA安全抗碰撞性算法版本实现细节性能优化发展历史应用案例密码学中的哈希函数一、哈希函数的定义哈希函数是一种数学函数,它接受任意长度的输入数据(......
  • LlamaIndex 探索视频系列
     如果您喜欢通过视频学习,现在正是查看我们的“探索LlamaIndex”系列的好时机。否则,我们建议您继续阅读“理解LlamaIndex”教程。自下而上开发(LlamaDocsBot)这是“探索LlamaIndex”系列中的一个子系列,向您展示如何从零开始构建文档聊天机器人。我们将以“自下而上”的方式......
  • 【内部项目预研】对信息分类进行探索
    分析输入信息的类别,目前是一个闭集、但是要按照开集的方式来进行分析;名称越乱越好,让系统自己来进行划分。必须首先考虑传统的方法;优先考虑数据结构的构建;强化监控机制的构建、首先进行认知和技术积累。一、数据情况找到了清华大学整理的关于体育的新闻,每篇一个新闻,第一行是标题,而......
  • IaC 管理新思路:Walrus 和 Terraform 的差异化探索
    Terraform的社区版本及商业化版本,让其成为在基础设施即代码(IaC)领域中可靠的部署和管理平台。尽管目前TerraformCloud/Enterprise仍然是最为广泛采用的IaC管理解决方案,但它存在一定的局限性。 随着用户需求和偏好的变化,以及鉴于成本考虑、灵活性需求以及简化复杂性的紧迫......
  • 区块链游戏:探索未来的可能性与挑战
    区块链游戏是一种将区块链技术应用于游戏领域的创新产品,它为游戏行业带来了全新的模式和可能性。本文将深入探讨区块链游戏的优点、挑战和未来趋势,帮助读者了解这一新兴领域。一、区块链游戏的优点1.公平性:区块链技术保证了游戏中的物品、货币等资源的真实性和可追溯性,避免......
  • Java高阶私房菜:探索泛型之妙用
        “泛型”(generics)作为Java特性之一,已经出现较长时间了,相信大家或多或少有接触过,接下来我们将系统重新回顾一下泛型,温故而知新,希望能有些新的启发。Java中的泛型作为V1.5后新增的特性,在JDK源码、中间件源码中有大量的使用,如果掌握了泛型将更容易理解源码,也提升代码抽......
  • 如何看待语音翻译在线翻译器?探索实时翻译的表现
    大家出门在外,相信多多少少都曾有机会体验与外国人交流,只是语言障碍让沟通变得不是那么顺利。好在还有语音翻译功能可以帮忙。这个功能还是很方便的,就比如你在国外旅行遇到当地人时,只需打开手机,启动语音翻译功能,即可实现翻译,从而畅快交流。这种便捷的体验,让人们更加愿意探索世......
  • 漏洞分类与实例解析:一场深入安全领域的探索之旅
    漏洞分类与实例解析:一场深入安全领域的探索之旅引言在网络安全的世界里,漏洞无处不在,犹如悬挂在信息空间之上的达摩克利斯之剑。正确识别并理解各类漏洞的特性和分类,是做好安全防护工作的基石。本文将深入探讨几种常见的漏洞类型——远程代码执行(RemoteCodeExecution,RC......