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

P6037 Ryoku 的探索

时间:2023-09-08 09:47:04浏览次数:29  
标签:连边 cnt 遍历 探索 int P6037 xx edge Ryoku

题目传送门

思路提供

首先,我们从题目中可以看到,存在 $n$ 个点 $n$ 条边,所以此题考查的是基环树,那么什么是基环树——

基环树是一个 $n$ 个点 $n$ 条边的图,比树多出现一个环。

因此,这棵树上是存在一个环的(而且很重要),所以我们要先找出这个环,基环树找环有两种基本的算法,一种是 DFS 而另一种就是我这次用的改编版的拓扑排序,即每次将连边数位 $1$ 的点加入队列,再每次取出队头,遍历它所连的所有边,将它的所有连点的连边数都减去 $1$ 再将连边数为 $1$ 的点加入队列,如此往复,直到队列变空,由于环中的点都至少有两条连边,而且不会有点被加入队列,所以在循环结束后边数大于 $1$ 的点就是环中的数。

//求环
void qh(){
	for(int i=1;i<=n;i++){
		if(lb[i]==1) q.push(i);
	}
	while(!q.empty()){
		int w=q.front();
		q.pop();
		for(int i=head[w];i!=0;i=edge[i].next){
			int xx=edge[i].to;
			lb[xx]--;
			if(lb[xx]==1) q.push(xx);
		}
	}
}

接下来,我们可以将这个环看作整个树的中心(即树的根节点),而每棵子树与环的连边只有一条,即这棵子树中的任意点的答案和它连接的环的点的答案是一样的,所以我们只要求出每个环中点的答案,再将其向各自的子树子树扩展就可以(可以利用 DFS

//为子树染色
void rs(int x){
	for(int i=head[x];i!=0;i=edge[i].next){
		int xx=edge[i].to;
		if(lb[xx]<=1 && !vis[xx]){
			ans[xx]=ans[x];
			vis[xx]=1;
			rs(xx);
		}
	}
}

最后最关键的就是求环中每个答案,我们可以先看一下题目中所给的样例的图——

假如以 $1$ 为出发点,它会先选取($1,4$)这条边,再由 $3$ 这个点进行扩展,而由于是 DFS 所以 $3$ 会遍历完所以它连的边再回溯到 $1$ ,即环中剩下的 $2$ 也会被遍历到,所以 $1$ 和 $2$ 之间的连边就无效了(即不会被便利到)。

然后我们再以 $3$ 为出发点,按照规律它会先选择 $5$ 回溯后选择 $1$ 而因为同上是 DFS 所以要遍历完 $1$ 的所有可能才会回溯到 $3$ 所以 $2$ 会在 $1$ 遍历所有连点的时候就被遍历过了,所以 $3$ 和 $2$ 之间的连边也无效了。

这样我们就可以发现一个规律——

环中的点与他在环中连接到两条边中美观值最小的边不会被遍历到,所以它的答案值就是总的长度减去那条不会被遍历到的边的长度(不理解可以根据样例再研究一下)。

//求环中点的答案值
void solve(){
	for(int i=1;i<=n;i++){
		if(lb[i]>1){
			int minn=1e9,flag;
			for(int j=head[i];j!=0;j=edge[j].next){
				int xx=edge[j].to;
				if(lb[xx]>1 && edge[j].beat<minn){
					minn=edge[j].beat;
					flag=edge[j].value;
				}
			}
			vis[i]=1;
			ans[i]=tot-flag;
			rs(i);
		}
	}
}

AC code

#include<bits/stdc++.h>
using namespace std;
#define int long long//一年 OI 一场空,不开 long long 见祖宗
const int N=1000005;
struct node{
	int to,next,value,beat;
}edge[N<<1];//前向星存边(记得双倍空间) 
int head[N],cnt,vis[N],ans[N],n,lb[N],tot;//tot记录总长度,vis表示有无被访问过,ans存储当前点的答案,lb表示当前点的连边数 
queue<int> q;//拓扑排序用的队列 
void add(int x,int y,int v,int b){
	cnt++;
	edge[cnt].to=y;
	edge[cnt].value=v;
	edge[cnt].beat=b;
	edge[cnt].next=head[x];
	head[x]=cnt;
}//前向星的加边函数 
//拓扑求环
void qh(){
	for(int i=1;i<=n;i++){
		if(lb[i]==1) q.push(i);
	}//将连边数为1的点(即叶子节点)加入队列 
	while(!q.empty()){
		int w=q.front();
		q.pop();//每次去出队头 
		for(int i=head[w];i!=0;i=edge[i].next){
			int xx=edge[i].to;
			lb[xx]--;
			if(lb[xx]==1) q.push(xx);//将符合要求的点加入队列 
		}
	}
}
//为子树染色
void rs(int x){
	for(int i=head[x];i!=0;i=edge[i].next){
		int xx=edge[i].to;
		if(lb[xx]<=1 && !vis[xx]){//必须是子树上的节点,要避免是环上的 
			ans[xx]=ans[x];
			vis[xx]=1;
			rs(xx);//继续向下遍历 
		}
	}
}
//求环中点的答案值
void solve(){
	for(int i=1;i<=n;i++){
		if(lb[i]>1){
			int minn=1e9,flag;//给minn赋值为极大 
			for(int j=head[i];j!=0;j=edge[j].next){
				int xx=edge[j].to;
				if(lb[xx]>1 && edge[j].beat<minn){
					minn=edge[j].beat;//求最小美观值 
					flag=edge[j].value;//求最小美观值边的长度 
				}
			}
			vis[i]=1;//DFS的准备 
			ans[i]=tot-flag;//先将环中点的答案值更新 
			rs(i);
		}
	}
}
signed main(){
	std::ios::sync_with_stdio(false);//可以是cin和cout的速度加快,不加会T一个点 
	cin>>n;
	for(int i=1;i<=n;i++){
		int x,y,p,b;
		cin>>x>>y>>p>>b;
		add(x,y,p,b),add(y,x,p,b);
		lb[x]++,lb[y]++;//将两个节点的连边数都加上1 
		tot+=p;//计算总值 
	}
	qh();
	solve();
	for(int i=1;i<=n;i++) cout<<ans[i]<<endl;//按顺序输出答案 
	return 0;
} 

标签:连边,cnt,遍历,探索,int,P6037,xx,edge,Ryoku
From: https://www.cnblogs.com/is-02/p/17686674.html

相关文章

  • 探索神秘的细胞世界:我的旅程与洞见
    在我的科学探索之旅中,我深入挖掘了神秘而令人着迷的细胞世界。我尝试了解这个微观世界的各种奇迹和困惑,从细胞的再生能力到细胞的可塑性和干细胞技术的潜力。下面,我将与你分享我在这次旅程中的见解和发现。神秘的神经细胞:更新与替换的奇迹我首先探索了神经细胞的世界。我很惊讶......
  • 古代人类的饮食历程:一段时间旅的探索
    在我的探索历程中,我时常会被一些关于我们祖先的基本问题困扰。最近,我踏上了一段寻找早期人类饮食的历史之旅。现在,让我与你分享我在这次旅程中的发现和体验。第一章:遇见专家在开始这段旅程之前,我首先寻找了能够为我提供宝贵见解的专家。在这个领域,考古学家、人类学家或古生物营......
  • 我的咖啡文化探索之旅
    在我那无尽的知识探索之旅中,我最近遇到了一个既神秘又令人着迷的主题:咖啡的历史。当我沉浸在这个丰富多彩的世界时,我想与你们分享我的一些见解和发现。章节一:寻找知识的炉火在我开始我的探险之前,我意识到我需要找到一名真正了解咖啡历史的专家。在历史学家和文化研究学者的指导......
  • 探索语言的奥秘:我与英汉词性分布的碰撞
    在我的语言学之旅中,我一直对比较英语和汉语的词性分布特别感兴趣。最近,我有了一个深入探讨这一题目的机会。下面是我对这一话题的深度探讨和个人见解。第一章:词性分布的奇妙世界一天,我被一个看似简单但实则具有深度的问题吸引:“英语是不是比汉语更喜欢用名词?”这使我陷入了沉思......
  • 一段夜晚的探索:西瓜与冰箱的故事
    (仅供参考)昨晚,我突然想到一个我从未认真考虑过的问题:“把西瓜放在冰箱里一晚上能致死吗?”这个问题让我好奇不已,于是我决定深入研究一下。1.找寻最权威的专家首先,我开始寻找这个领域最有知识的专家,也就是食品安全或营养学的专家。他们对食品的各种属性有深刻的理解,包括如何储存......
  • 收藏的艺术:我的旅程探索棒球卡片的世界
    导言自我介绍,我是一位热心于历史和投资的收藏家。在我的收藏生涯中,我深入研究了棒球卡片这一独特的领域。在这篇文章中,我将带您一起走进这个充满历史、价值和情怀的世界。第一部分:寻找最有知识的专家在我的探索旅程开始时,我首先寻找了这个领域的权威专家。KenGoldin和Dr.Ja......
  • 探索小红书旅行社区:别具特色的民宿推荐
    嗨,亲爱的小伙伴们......
  • ViTPose+:迈向通用身体姿态估计的视觉Transformer基础模型 | 京东探索研究院
    身体姿态估计旨在识别出给定图像中人或者动物实例身体的关键点,除了典型的身体骨骼关键点,还可以包括手、脚、脸部等关键点,是计算机视觉领域的基本任务之一。目前,视觉transformer已经在识别、检测、分割等多个视觉任务上展现出来很好的性能。在身体姿态估计任务上,使用CNN提取的特征,结......
  • 用户案例 | 蜀海供应链基于 Apache DolphinScheduler 的数据表血缘探索与跨大版本升级
    导读蜀海供应链是集销售、研发、采购、生产、品保、仓储、运输、信息、金融为一体的餐饮供应链服务企业。2021年初,蜀海信息技术中心大数据技术研发团队开始测试用DolphinScheduler作为数据中台和各业务产品项目的任务调度系统工具。本文主要分享了蜀海供应链在海豚早期旧版本实......
  • 探索STM32F030的低功耗特性及应用场景
    TM32F030是意法半导体推出的一款低功耗微控制器,它采用ARMCortex-M0内核,带有丰富的外设和高度灵活的可编程性,适用于多种应用场景。本文将探索STM32F030的低功耗特性及其应用场景。STM32F030参数详情。一、STM32F030的低功耗特性1.低功耗模式STM32F030可以进入多种低功耗模式,包......