[CSU - 1811 (湖南省赛16)] Tree Intersection (启发式合并)

2024-06-21 19:38

本文主要是介绍[CSU - 1811 (湖南省赛16)] Tree Intersection (启发式合并),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CSU - 1811 (湖南省赛16)

给定一棵树,每个节点都有一个颜色
问割掉任意一条边,生成的两个子树中颜色集合的交集大小


问题可以转化为任意一棵子树中,
这个子树中的颜色数量和只在这个子树中出现的颜色的数量
用总的颜色数量减去独有颜色数量即为这棵子树的答案

从 lcy大爷那里学到了机智的启发式合并的做法
对每个点维护一个 map
来记录这个点为根的子树中颜色的及其数量
然后dfs一遍,对每个节点启发式地将其儿子的map合并到父亲上
合并的时候,如果发现一个颜色出现次数用完了
说明它只在这个子树中出现,所以 res++
最后一个节点 u 连向父亲边的答案即为 map[u].size()-res
注意儿子中的 res 要累加到父亲上,
并且统计的时候要记一个 vis,免得算重了

由于采用了启发式合并,所以总的时间复杂度只有 (nlog2(n))
由于每次都最多只有一个 map,所以总的空间复杂度是 (n)
虽然还有时间 (nlogn) 的做法,但我觉得能过就行
况且启发式合并编码复杂度极低,并且具有很好的推广性
从某些角度甚至优于 (nlogn) 的做法

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <string>
#include <complex>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")const int maxn=1e5+10;
struct Graph
{int ndn,edn,last[maxn];int u[2*maxn], v[2*maxn], nxt[2*maxn];void init(int _n){ndn=_n; edn=0; MST(last,-1);}void adde(int _u, int _v){u[edn]=_u; v[edn]=_v;nxt[edn]=last[_u];last[_u]=edn++;}
};int N;
int col[maxn], cnt[maxn], id[maxn], ans[maxn], vis[maxn];
map<int,int> have[maxn];
Graph G;int dfs(int,int);int main()
{#ifdef LOCALfreopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);#endifwhile(~scanf("%d", &N)){G.init(N); CLR(cnt); CLR(vis);for(int i=1; i<=N; i++) scanf("%d", &col[i]), cnt[col[i]]++;for(int i=0,u,v; i<N-1; i++){scanf("%d%d", &u, &v);G.adde(u,v); G.adde(v,u);}id[1]=-1;dfs(1,0);for(int i=0; i<N-1; i++) printf("%d\n", ans[i]);}return 0;
}int dfs(int u, int f)
{int res=0;have[u].clear();for(int e=G.last[u],v; ~e; e=G.nxt[e]) if((v=G.v[e])!=f){id[v] = e>>1;res += dfs(v,u);if(have[u].size()<have[v].size()) swap(have[u], have[v]);for(auto &pr:have[v]){have[u][pr.first] += pr.second;if(have[u][pr.first] == cnt[pr.first] && !vis[pr.first]){res++;vis[pr.first] = 1;}}have[v].clear();}have[u][col[u]] ++;if(have[u][col[u]] == cnt[col[u]] && !vis[col[u]]){res++;vis[col[u]] = 1;}if(~id[u]) ans[id[u]] = have[u].size() - res;return res;
}

这篇关于[CSU - 1811 (湖南省赛16)] Tree Intersection (启发式合并)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082145

相关文章

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

【Qt6.3 基础教程 16】 掌握Qt中的时间和日期:QTimer和QDateTime的高效应用

文章目录 前言QTimer:定时任务的强大工具QTimer的基本用法高级特性:单次定时器 QDateTime:处理日期和时间获取当前日期和时间日期和时间的格式化输出日期和时间计算 用例:创建一个倒计时应用结论 前言 在开发桌面应用程序时,处理时间和日期是一个常见且重要的任务。Qt框架提供了强大的工具来处理与时间相关的功能,其中QTimer和QDateTime是最核心的类。本

JeecgBoot v3.7.0 all 版本发布,前后端合并一个仓库

项目介绍 JeecgBoot是一款企业级的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue3,Mybatis-plus,Shiro,JWT 支持微服务。强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开

Linux float int和16进制互相转换

Linux 上float int和16进制互换操作。之前把float转16进制,也就是转成4个字节,方便使用串口传输嘛。使用的方法是: //float 转 16进制float x_pid_p = 15.0;unsigned char * bValue = (unsigned char *)& x_pid_p;printf("%x\t%x\t%x\t%x\n", bValue[0], bVa

2021-02-16物料档案条码添加和蓝牙条码标签打印,金蝶安卓盘点机PDA,金蝶仓库条码管理WMS系统

物料档案条码添加和蓝牙条码标签打印,金蝶安卓盘点机PDA https://member.bilibili.com/platform/upload-manager/article 本期视频我们来讲解一下汉点机PDA条码添加和条码标签蓝牙便携打印: 在实际使用中,我们商品有两种情况: 一种是商品本身就有条码, 比如:超市卖的可口可乐,牛奶等商品,商品本身就有69开头的国标码,那么我们就可以使用盘点

玩转Web之easyui(二)-----easy ui 异步加载生成树节点(Tree),点击树生成tab(选项卡)

关于easy ui 异步加载生成树及点击树生成选项卡,这里直接给出代码,重点部分代码中均有注释 前台: $('#tree').tree({ url: '../servlet/School_Tree?id=-1', //向后台传送id,获取根节点lines:true,onBeforeExpand:function(node,param){ $('#tree').tree('options'

Python批量读取csv文件并合并文件

import pandas as pdimport os # 获取当前路径cwd = os.getcwd()# 要拼接的文件夹及其完整路径,注不要包含中文## 待读取批量csv的文件夹 read_path = 'data_Q1_2018' ## 待保存的合并后的csv的文件夹 save_path = 'data_Q1_2018_merge' ## 待保存

【C++PCL】点云处理Kd-tree原理

作者:迅卓科技 简介:本人从事过多项点云项目,并且负责的项目均已得到好评! 公众号:迅卓科技,一个可以让您可以学习点云的好地方 重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的地方。 目录         1.原理介绍 1.原理介绍         kd-tree是散乱点云的一种储存结构,它是一种

[图解]建模相关的基础知识-16

1 00:00:00,350 --> 00:00:04,130 刚才那个,就相当于,12这个我们可以认为是什么 2 00:00:05,020 --> 00:00:11,360 我们用类图来表达就是,员工、电话 3 00:00:13,320 --> 00:00:15,080 多个 4 00:00:15,090 --> 00:00:16,440 当然这个电话这里 5 00:00:16,970

数据库阿里连接池 druid配置详解 标签: druidspringjavaxml配置阿里池 2016-06-16 00:34 57532人阅读 评论(11) 收藏 举报 版权声明:本文为博主原创文

数据库阿里连接池 druid配置详解 标签: druidspringjavaxml配置阿里池 2016-06-16 00:34  57532人阅读  评论(11)  收藏  举报 版权声明:本文为博主原创文章,未经博主允许不得转载。 java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,有不得不使用数据库连接池。数据库连接池有很多选择,c3p、dh