F - Tree Intersection CSU - 1811

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

4
1 2 2 1
1 2
2 3
3 4
5
1 1 2 1 2
1 3
2 3
3 5
4 5

Sample Output

1
2
1
1
1
2
1 题意:给一棵带有颜色的树,去掉某一条边后,他就变成了两个连通块,求这两个连通块的颜色交集的大小。(对每条边求一次)
思路:首先我们可以预处理出来整棵树的颜色,去掉一条边,就相当于一颗子树独立出来了,就变成了一颗子树,和剩余的树,可以将子树的颜色处理出来,然后剩余的那棵树的颜色也求出来了(等于整树 减去 子树)。
子树的话我们就可以用启发性合并去求颜色。但是要注意一下细节,看下代码吧。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn=1e5+;
int n,m;
int mx,big,id,sum;
int col[maxn],deep[maxn],num[maxn],si[maxn],hson[maxn],cnt[maxn],ans[maxn];
int l[maxn],r[maxn];
vector<int>G[maxn]; void findhson(int x,int fa,int dep)//找到所有的重儿子,并求出其深度
{
si[x]=;
deep[x]=dep;
int len=G[x].size();
for(int i=;i<len;i++)
{
int t=G[x][i];
if(t!=fa)
{
findhson(t,x,dep+);
si[x]+=si[t];
deep[t]=deep[x]+;
if(si[t]>si[hson[x]])
hson[x]=t;
}
}
}
void cal(int x,int fa,int val)
{
cnt[col[x]]+=val;
if(cnt[col[x]]==)//如果新出现一种颜色就说明重合的数量多了一个
sum++;
if(cnt[col[x]]==num[col[x]])/*如果这个这个子树的该颜色数量等于整棵树的该
颜色数量,就说明两棵子树的重合数量减一*/
sum--;
int len=G[x].size();
for(int i=;i<len;i++)
{
int t=G[x][i];
if(t!=fa && t!=big)
cal(t,x,val);
}
}
void dfs(int x,int fa,int flag)
{
int len=G[x].size();
for(int i=;i<len;i++)
{
int t=G[x][i];
if(t!=fa && t!=hson[x])
dfs(t,x,);
}
if(hson[x])
{
dfs(hson[x],x,);
big=hson[x];
}
cal(x,fa,);
big=;
ans[x]=sum;
if(!flag)
{
cal(x,fa,-);
sum=;
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
big=;sum=;
for(int i=;i<=n;i++)
{
G[i].clear();
num[i]=si[i]=hson[i]=cnt[i]=ans[i]=;
}
for(int i=;i<=n;i++)
{
scanf("%d",&col[i]);
num[col[i]]++;//记录每个颜色的数量
}
int x,y;
for(int i=;i<n;i++)
{
scanf("%d %d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
l[i]=x;r[i]=y;//记录其子节点和父亲节点
}
findhson(,,);
dfs(,,);
for(int i=;i<n;i++)
{
int j;
if(deep[l[i]]>deep[r[i]])//这个看我等会传的图就知道为什么要比较一下了
j=l[i];
else
j=r[i];
printf("%d\n",ans[j]);
}
}
return ;
}

为什么要比较深度?因为我们根固定,我们启发式合并只会求方框内的那个子树的情况,而并不会求剩余的那块的子树的情况。所以在计算的时候选择深度高的那颗子树去进行计算才是正确的。

启发式合并CSU - 1811的更多相关文章

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

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

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

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

  3. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  4. 【BZOJ3123】森林(主席树,启发式合并)

    题意:一个带点权的森林,要求维护以下操作: 1.询问路径上的点权K大值 2.两点之间连边 n,m<=80000 思路:如果树的结构不发生变化只需要维护DFS序 现在因为树的结构发生变化,要将两棵 ...

  5. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

  6. 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并

    启发式合并而已啦,, 调试时发现的错误点:insert后没有splay,把要拆开的树的点插入另一个树时没有把ch[2]和fa设为null,找第k大时没有先减k,,, 都是常犯的错误,比赛时再这么粗心就 ...

  7. 51nod 1515 明辨是非 并查集 + set + 启发式合并

    给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等:否则输出NO,并忽略此次操作. 当p为0时,如果第x变量和第y个变量可以不相等,则输 ...

  8. [BZOJ 1483][HNOI 2009]梦幻补丁(有序表启发式合并)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1483 分析: 先将不同的颜色的出现位置从小到大用几条链表串起来,然后统计一下答案 对于 ...

  9. 【BZOJ-2809】dispatching派遣 Splay + 启发式合并

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2334  Solved: 1192[Submi ...

随机推荐

  1. 超强XSS攻击利器

    ======================================================================= BackTrack 5 R1 XSS研究之XSSer(超 ...

  2. E20170524-hm

    logging   n. <美>伐木搬运业; 记录,存入; 航行日志; inversion  n. 倒置; 转化; (尤指词序) 倒装; (染色体的) 倒位; reversion   n. ...

  3. SAS基础 -- SAS编程入门

    SAS语言 -- 简介   SAS语言是一种专用的数据管理与分析语言,它提供了一种完善的编程语言.类似于计算机的高级语言,SAS用户只需要熟悉其命令.语句及简单的语法规则就可以做数据管理和分析处理工作 ...

  4. Git学习三

    一.准备Github远程仓库 1.github官网注册账户 2.ubuntu端创建SSH Key $ssh-keygen -t rsa -C "youremail@example.com&q ...

  5. 一文了解H5照片上传过程

    一.选择拍照或文件 HTML: 使用<input>标签, type设为"file"选择文件, accept设为"image/*"选择文件为图片类型和 ...

  6. crm-vue项目上线前对加载速度以及兼容IE的一些方法

    一.关于IE浏览器适配 打包前我们可以在package.json文件做如下配置 "browserslist": [ "> 1%", "last ...

  7. 【底层原理】高级开发必须懂的"字节对齐"

    认识字节对齐之前,假定int(4Byte),char(1Byte),short(2Byte) 认识字节对齐 先看段代码: struct Data1 { char a; int b; short c; ...

  8. 标准行cp功能

    #include<stdio.h> int main(int argc,char *argv[]) { FILE *src_fp,*des_fp; ]={}; ) { printf(&qu ...

  9. java之数据处理,小数点保留位数

    1.返回字符串类型,保留后两位: public static String getRate(Object d) { return String.format("%.2f", d); ...

  10. 特性property

    #property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用# class People:# def __init__(self,name,weight,height ...