首页 > 其他分享 >codeforces round 975 E(div.2)(lambda表达式实现dfs,min_element函数,一定要优化重复的步骤)

codeforces round 975 E(div.2)(lambda表达式实现dfs,min_element函数,一定要优化重复的步骤)

时间:2024-09-30 18:45:33浏览次数:6  
标签:975 min dep auto codeforces dfs int 深度 节点

解题历程:

看到题目要求要用最少的消除次数让所有叶子深度相同,通过观察,那么就只需要将所有深度都尝试一遍就行了,可是我当时没多想就用dfs记录所有节点的深度,单独将所有叶子和该叶子的深度存起来,记录最大的深度,从最大深度尝试到深度0,对于深度小于当前尝试深度的叶子,用dfs的方式将与该叶子直接关联的度数小于等于二的节点删除,删除就用一个数组进行标记删除的节点,利用这个原理写一个删除函数,传递的参数就是目标深度和叶子节点的坐标,返回的就是删除步数,这样每层就遍历一次将遍历的结果相加取最小值就是答案,结果超时了,写这个代码写了一个小时,比赛也只剩几分钟了,寄。然后看了高手的代码,发现我的思路没有问题,就是遍历每个深度的方法有问题,遍历时有太多的重复删除。

正确思路:于是我又想到从小的深度往大的深度遍历,利用一个数组记录当前节点子树总数,当前节点也计入其中,那么就可以采用层序遍历的方式遍历树,要删除的步数就是这层节点所有子树节点的总数,和小于这层的分支的节点数,那么就用一个数组记录该节点子树的最大深度,这个数组用于区分要删掉的低于遍历深度的叶子分支,由于删掉的分支在后面的层数都要删掉,就可以用一个变量记录要删除的分支节点数,每遍历一层就加上记录的次数那么就可以得到等式:所有叶子变成当前深度所以需要的步数=小于当前层数叶子的分支节点数+当前深度的所有节点的子树节点数

代码:

#include<bits/stdc++.h>
using namespace std;

void solve()
{
	int n;
	cin>>n;
	vector<vector<int>>a(n+1);
	vector<int>b(n+1,1),f(n+1,n),dep(n+1),m(n+1);
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	int t=0;
	auto dfs=[&](auto& self,int x,int p)->void
	{
		m[x]=dep[x];
		for(auto y:a[x])
		{
			if(y==p)continue;
			dep[y]=dep[x]+1;//记录深度。dfs往下探时的操作
			self(self,y,x);
			m[x]=max(m[y],m[x]);//dfs往回缩时的操作
			b[x]+=b[y];//记录当前节点及以下的节点总数
		}
		
	};
	dfs(dfs,1,0);
	int l=1;
	auto dfss=[&](auto& self,int x)->void//标记需要删除的包含叶子x的分支
	{
		for(auto y:a[x])
		{
			if(dep[y]<dep[x])
			{
				
				if(m[x]!=m[y])//最大深度不同或已被删除
				{
					m[x]=0;
					break;
				}
				m[x]=0;
				l++;
				self(self,y);
			}
		}
	};
	queue<int>q;
	q.push(1);
	int s=0;
	while(!q.empty())
	{
		auto u=q.front();
		l=1;
		if(a[u].size()==1&&u!=1)//坑点,没有u!=1根节点会被当成叶子节点删除
		{
			dfss(dfss,u);
			s+=l;			
		}
		q.pop();
		for(auto i:a[u])
		{
			if(dep[i]>dep[u])
			{
				f[dep[u]]+=b[i];
				q.push(i);
			}
		}
		if(q.empty()||dep[u]!=dep[q.front()])//坑点,先判断空在进行后面的判断
		{
			f[dep[u]]+=t;
			if(!q.empty())
			f[dep[q.front()]]=0;
			t+=s;
			s=0;
		}
	}
	int ans=*min_element(f.begin(),f.end());//以后不用for循环找最值了
	cout<<ans<<endl;
}

int main(void )
{   
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
    int test=1;
    cin>>test;
    while(test--)
    {
    	solve();
	}
    return 0;
}

反思与收获:

  1. 有思路后开始写代码之前要思考一下有没有重复的步骤,如果有的话就要进行优化,不要有侥幸心理,一旦超时就要浪费大量的时间。

  2. 以后可以用lambda表达式写函数,这样写的函数可以不用提前声明,其标准格式为

auto function=[&](int a,int b)->void{
    cout<<a+b<<endl;
}

int n;
auto dfs[&](auto& self,int a,int b)->void{//void是返回值
//[&]表示函数前面的变量都可以在函数里面使用,比如下面的n
    n+=3;
    self(self,c,a);//c为当前节点,a为上一节点,a是为了避免重复访问父节点
}
dfs(dfs,1,0);
  1. 以后可以用min_element函数查找数组的最值
  2. 以后注意度数为1的根
  3. 先判断是否为空

标签:975,min,dep,auto,codeforces,dfs,int,深度,节点
From: https://www.cnblogs.com/cavendishboys/p/18442320

相关文章

  • WPF Progrss bar stringformat {} {0}% IsDetermined
    //xaml<Windowx:Class="WpfApp425.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mi......
  • Codeforces Round 976 (Div. 2) and Divide By Zero 9.0
    目录写在前面A签到B数学,模拟C二进制,拆位D暴力,并查集E概率DPF写在最后写在前面补题地址:https://codeforces.com/gym/104128。上大分失败呃呃呃呃有点过载了妈的我现在应该去打会儿游戏。A签到等价于求\(n\)在\(k\)进制下各位之和,写一个类似快速幂的东西。///*By......
  • Django-admin管理工具
    一、Djangoadmin组件使用Django提供了基于web的管理工具:amdin组件。admin可以对注册完的数据进行增删改成操作。 一)项目的配置文件(settings.py)相关配置Django自动管理工具是django.contrib的一部分。你可以在Django项目的settings.py中INSTALLED_APPS看到......
  • Codeforces Round 975 (Div. 2)
    C.CardsPartition(C)对于每个确定的size,有便捷的方法判断该值是否合法:组数最小为\(a_{max}\),若\(k\)张牌可以填出\(a_{max}\)组牌堆则合法;将余下的牌当成新的一组,若\(k\)张牌可以凑出一整组则合法;其余情况不合法。由于check过程为\(O(1)\),可从大到小暴力枚举size,时间......
  • Codeforces Round 976 (Div. 2)
    传送门A.输出\(n\)在\(k\)进制下各数位之和B.一个位置被反转当且仅当有奇数个因子,有奇数个因子的数一定是完全平方数。二分\(n\)即可C.枚举二进制下每一位,发现\(b,c,d\)再这一位最多有八种可能,对于每一种情况都能得到在这一位\(a\)的值,分类讨论就行了。D.E.\(......
  • CF582D Number of Binominal Coefficients 题解
    CF582DNumberofBinominalCoefficients题解纪念一下自己第一道独立A掉的黑题/CF3300。题目大意给定质数\(p\)和整数\(\alpha,A\),求满足\(0\lek\len\leA\)且\(p^{\alpha}|\binomnk\)的数对\((n,k)\)的个数。Solve首先,我们引入Kummer定理,即:\(p\)在......
  • Minstrel自动生成结构化提示,让AI为AI写提示词的多代理提示生成框架
    在人工智能快速发展的今天,如何有效利用大型语言模型(LLMs)成为了一个普遍关注的话题。这是9月份的一篇论文,提出了LangGPT结构化提示框架和Minstrel多代理提示生成系统,为非AI专家使用LLMs提供了强大支持。对于非人工智能专家来说,构建高质量的提示以充分利用LLMs的能力仍然是一个巨大......
  • Codeforces Round 976 (Div. 2)
    B:很容易发现只有因数个数为偶数的灯泡是亮的。所以只有完全平方数的因数是奇数个。实现上可以二分。但是sqrt是double的必须开sqrtl才是longdouble的,才能满足这题longlong的数据范围。人给我卡傻了。哈哈。#include<bits/stdc++.h>usingnamespacestd;#defineintunsign......
  • terminalizer - 录制终端生成 gif
    文章目录一、关于terminalizer效果展示特点下一步是什么?二、安装三、基本入门压缩四、使用Init配置记录播放渲染分享生成五、配置录制延时GIF终端主题水印FrameBox空帧WindowFrame浮动Frame实心Frame没有标题的实心FrameStylingHint六、FAQ&Issues如何支持Z......
  • Codeforces Round 975 (Div. 2) CE
    来源:CodeforcesRound975(Div.2)C.CardsPartition题意本身有\(a_i\)张\(i\)牌,现在将牌分成若干份,每一份牌数相等,且每一份都由不同的牌组成同时有\(k\)次补充任意牌的机会,求最多分成一份几张牌思路假定分成\(m\)份,每份\(p\)张牌,那么所有牌加补充的牌等于\(m*p......