Bobo has a tree with n vertices numbered by 1,2,…,n and (n-1) edges. The i-th vertex has color c i, and the i-th edge connects vertices a i and b i.
Let C(x,y) denotes the set of colors in subtree rooted at vertex x deleting edge (x,y).
Bobo would like to know R_i which is the size of intersection of C(a i,b i) and C(bi,a i) for all 1≤i≤(n-1). (i.e. |C(a i,b i)∩C(b i,a i)|)

Input

The input contains at most 15 sets. For each set:
The first line contains an integer n (2≤n≤10 5).
The second line contains n integers c 1,c 2,…,c n (1≤c_i≤n).
The i-th of the last (n-1) lines contains 2 integers a i,b i (1≤a i,b i≤n).

OutputFor each set, (n-1) integers R 1,R 2,…,R n-1.Sample Input

  1. 4
  2. 1 2 2 1
  3. 1 2
  4. 2 3
  5. 3 4
  6. 5
  7. 1 1 2 1 2
  8. 1 3
  9. 2 3
  10. 3 5
  11. 4 5

Sample Output

  1. 1
  2. 2
  3. 1
  4. 1
  5. 1
  6. 2
  7. 1

Hint

题解:题意就是,给以一颗树n个节点,每个节点有一种颜色,然年后对于n-1条边,如果把一条边截断,让你求两颗子树有多少种相同的颜色,依次输入每一条边的答案。

启发式搜索,分别记录点和边的答案;如果点u和其子树某种颜色的数量已经等于总量了,那么对于该子树外的一部分,就没有该中颜色了,答案-1;如果小于总量,答案+1;

然后更新u节点该颜色的数量即可;

参考代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define clr(a,val) memset(a,val,sizeof (a))
  4. #define pb push_back
  5. #define fi first
  6. #define se second
  7. typedef long long ll;
  8. const int maxn=1e5+;
  9. inline int read()
  10. {
  11. int x=,f=;char ch=getchar();
  12. while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
  13. while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
  14. return x*f;
  15. }
  16. struct Edge{
  17. int to,index,nxt;
  18. } edge[maxn<<];
  19. int n,head[maxn<<],tot;
  20. int col[maxn],sum[maxn],ans[maxn],res[maxn<<];//ans[u]表示u点及子节点的答案, res[edge]表示边的答案
  21. map<int,int> cnt[maxn];//cnt[u][color] 表示u点子树color颜色有多少个节点
  22.  
  23. inline void Init()
  24. {
  25. clr(head,-);clr(sum,); tot=;
  26. for(int i=;i<=n;++i) cnt[i].clear();
  27. }
  28.  
  29. inline void addedge(int u,int v,int id)
  30. {
  31. edge[tot].to=v;
  32. edge[tot].index=id;
  33. edge[tot].nxt=head[u];
  34. head[u]=tot++;
  35. }
  36.  
  37. inline void dfs(int u,int fa,int id)
  38. {
  39. cnt[u][col[u]]=;
  40. ans[u] = cnt[u][col[u]]<sum[col[u]]?:;
  41. for(int e=head[u];~e;e=edge[e].nxt)
  42. {
  43. int v=edge[e].to;
  44. if(v==fa) continue;
  45. dfs(v,u,edge[e].index);
  46. if(cnt[u].size()<cnt[v].size())
  47. {
  48. swap(cnt[u],cnt[v]);
  49. swap(ans[u],ans[v]);
  50. }
  51. map<int,int>::iterator it;
  52. for(it=cnt[v].begin();it!=cnt[v].end();it++)
  53. {
  54. if(!cnt[u][(*it).fi] && (*it).se<sum[(*it).fi]) ++ans[u];
  55. else if(cnt[u][(*it).fi] && cnt[u][(*it).fi]+(*it).se==sum[(*it).fi]) --ans[u];
  56. cnt[u][(*it).fi]+=(*it).se;//加上子树的数量
  57. }
  58. }
  59. res[id]=ans[u];
  60. }
  61.  
  62. int main()
  63. {
  64. while(~scanf("%d",&n))
  65. {
  66. Init();
  67. for(int i=;i<=n;++i) col[i]=read(),sum[col[i]]++;
  68. for(int i=;i<n;++i)
  69. {
  70. int u=read(),v=read();
  71. addedge(u,v,i);addedge(v,u,i);
  72. }
  73. dfs(,,);
  74. for(int i=;i<n;++i) printf("%d\n",res[i]);
  75. }
  76.  
  77. return ;
  78. }

CSUOJ1811 Tree Intersection (启发式合并)的更多相关文章

  1. csu oj 1811: Tree Intersection (启发式合并)

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1811 给你一棵树,每个节点有一个颜色.问删除一条边形成两棵子树,两棵子树有多少种颜色是有 ...

  2. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  3. dsu on tree[树上启发式合并学习笔记]

    dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有 ...

  4. dsu on tree (树上启发式合并) 详解

    一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

  5. AGC 014E.Blue and Red Tree(思路 启发式合并)

    题目链接 \(Description\) 给定两棵\(n\)个点的树,分别是由\(n-1\)条蓝边和\(n-1\)条红边组成的树.求\(n-1\)次操作后,能否把蓝树变成红树. 每次操作是,选择当前树 ...

  6. dsu on tree(树上启发式合并)

    简介 对于一颗静态树,O(nlogn)时间内处理子树的统计问题.是一种优雅的暴力. 算法思想 很显然,朴素做法下,对于每颗子树对其进行统计的时间复杂度是平方级别的.考虑对树进行一个重链剖分.虽然都基于 ...

  7. CSU 1811: Tree Intersection(线段树启发式合并||map启发式合并)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1811 题意:给出一棵树,每一个结点有一个颜色,然后依次删除树边,问每次删除树边之后,分开的两个 ...

  8. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

  9. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

随机推荐

  1. Github PageHelper 原理解析

    任何服务对数据库的日常操作,都离不开增删改查.如果一次查询的纪录很多,那我们必须采用分页的方式.对于一个Springboot项目,访问和查询MySQL数据库,持久化框架可以使用MyBatis,分页工具 ...

  2. Python日志模块logging简介

    日志处理是项目的必备功能,配置合理的日志,可以帮助我们了解系统的运行状况.定位位置,辅助数据分析技术,还可以挖掘出一些额外的系统信息. 本文介绍Python内置的日志处理模块logging的常见用法. ...

  3. 领扣(LeetCode)错误的集合 个人题解

    集合 S 包含从1到 n 的整数.不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复. 给定一个数组 nums 代表了集合 S ...

  4. 0MQ宗旨

    先来看<Implementing distributed applications with 0MQ and some other bad guys...>.用0MQ去实现分布应用,或者用 ...

  5. uniapp打包Android APP

    1.uniAPP 将项目打包成,打包成功后格式如下 2.下载相关工具 Android studio(打包成app的工具) 和Hbuilder官方SDK,安装解压响应工具 3. 用 Android st ...

  6. Python拼接字符串的七种方式

    忘了在哪看到一位编程大牛调侃,他说程序员每天就做两件事,其中之一就是处理字符串.相信不少同学会有同感. 几乎任何一种编程语言,都把字符串列为最基础和不可或缺的数据类型.而拼接字符串是必备的一种技能.今 ...

  7. iOS开发调试概览

    概述 我们都知道Xcode默认的调试器是LLDB(在此之前使用的是GDB),但是关于LLDB的debug技巧并非所有人都比较清楚,可能所有人都知道p或者po命令打印一些变量.但是实际的情况时这些还远远 ...

  8. OpenStack集成ceph

    openstack组件集成ceph OpenStack集成ceph详细过程可以查看ceph官方文档:ceph document OpenStack Queens版本,1台控制节点controller, ...

  9. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  10. 为宇宙第一强的IDE干一票

    背景 在博客园看到很多人说.net在国内已死,很多人在为.net前途担忧,包括一些创业大佬也提及到这些问题,提及到客户指定了说使用php或者java. 那么基本可以确认了,.net 处于风雨漂泊的地位 ...