csu oj 1811: Tree Intersection (启发式合并)
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1811
给你一棵树,每个节点有一个颜色。问删除一条边形成两棵子树,两棵子树有多少种颜色是有相同的。
启发式合并,小的合并到大的中。类似的题目有http://codeforces.com/contest/600/problem/E
//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int N = 1e5 + ;
struct Edge {
int next, to, index;
}edge[N << ];
int color[N], head[N], tot;
int sum[N], ans[N], res[N]; //sum[color]:颜色color节点个数, ans[u]表示u点及字节点的答案, res[edge]表示边的答案
map <int, int> cnt[N]; //cnt[u][color] 表示u点子树color颜色有多少个节点 void init(int n) {
for(int i = ; i <= n; ++i) {
head[i] = -;
sum[i] = ;
cnt[i].clear();
}
tot = ;
} inline void add_edge(int u, int v, int id) {
edge[tot].next = head[u];
edge[tot].to = v;
edge[tot].index = id;
head[u] = tot++;
} void dfs(int u, int pre, int id) {
cnt[u][color[u]] = ;
ans[u] = cnt[u][color[u]] < sum[color[u]] ? : ;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre)
continue;
dfs(v, u, edge[i].index);
if(cnt[u].size() < cnt[v].size()) {
swap(cnt[u], cnt[v]);
swap(ans[u], ans[v]);
}
for(auto it : cnt[v]) {
int &num = cnt[u][it.first];
if(num == && num + it.second < sum[it.first]) {
++ans[u];
} else if(num + it.second == sum[it.first] && num) { //说明此子树的it.first颜色节点个数已满
--ans[u];
}
num += it.second;
}
}
res[id] = ans[u];
} int main()
{
int n, u, v;
while(scanf("%d", &n) != EOF) {
init(n);
for(int i = ; i <= n; ++i) {
scanf("%d", color + i);
++sum[color[i]];
}
for(int i = ; i < n; ++i) {
scanf("%d %d", &u, &v);
add_edge(u, v, i);
add_edge(v, u, i);
}
dfs(, -, );
for(int i = ; i < n; ++i) {
printf("%d\n", res[i]);
}
}
return ;
}
csu oj 1811: Tree Intersection (启发式合并)的更多相关文章
- CSU 1811: Tree Intersection(线段树启发式合并||map启发式合并)
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1811 题意:给出一棵树,每一个结点有一个颜色,然后依次删除树边,问每次删除树边之后,分开的两个 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- dsu on tree[树上启发式合并学习笔记]
dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有 ...
- dsu on tree (树上启发式合并) 详解
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...
- AGC 014E.Blue and Red Tree(思路 启发式合并)
题目链接 \(Description\) 给定两棵\(n\)个点的树,分别是由\(n-1\)条蓝边和\(n-1\)条红边组成的树.求\(n-1\)次操作后,能否把蓝树变成红树. 每次操作是,选择当前树 ...
- 【树状数组】CSU 1811 Tree Intersection (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1811 题目大意: 一棵树,N(2<=N<=105)个节点,每个节点有一种颜 ...
- CSU 1811 Tree Intersection
莫队算法,$dfs$序. 题目要求计算将每一条边删除之后分成的两棵树的颜色的交集中元素个数. 例如删除$u->v$,我们只需知道以$v$为$root$的子树中有多少种不同的颜色(记为$qq$), ...
- dsu on tree(树上启发式合并)
简介 对于一颗静态树,O(nlogn)时间内处理子树的统计问题.是一种优雅的暴力. 算法思想 很显然,朴素做法下,对于每颗子树对其进行统计的时间复杂度是平方级别的.考虑对树进行一个重链剖分.虽然都基于 ...
- 启发式合并CSU - 1811
F - Tree Intersection CSU - 1811 Bobo has a tree with n vertices numbered by 1,2,…,n and (n-1) edges ...
随机推荐
- SQL 数据库表标识列初始化 DBCC
把ArimaIndexForecastModel这张表的标识列重置为0,前提是这张表执行过删除操作 示例: dbcc checkident('ArimaIndexForecastModel',res ...
- rmmod 无法卸载模块问题
用insmod加载驱动模块成功后,用rmmod无法卸载 解决方法:在板子上建立一个空目录:lib/modules/2.6.30.4/
- 【转】strcpy溢出的攻击示例
在学习c/c++的时候,就讲到了一些C类型的字符串函数不是安全的,比如strcpy没有检查长度会溢出,推荐使用strncpy,笔试面试也经常问到.同时经常浏览安全相关的新闻,缓冲区溢出攻击是很常见的一 ...
- jquery中html()/text()/val()区别
html就是你可以添加<span></span><li></li>的标记text只能写文本如果写了上面的标记则会以文本形式输出,就是输出标签体的内容va ...
- context-param引发spring容器以及servlet容器的关联
转自:http://blog.csdn.net/liaoxiaohua1981/article/details/6759206 格式定义: [html] view plaincopy <cont ...
- 正则表达式 java版
众所周知,在程序开发中,难免会遇到需要匹配.查找.替换.判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力.因此,学习及使用正则表达式,便成了解决这一矛 ...
- Python中字符串的使用
这篇文章主要介绍python当中用的非常多的一种内置类型——str.它属于python中的Sequnce Type(序列类型).python中一共7种序列类型,分别为str(字符串),unicode( ...
- 【英语】Bingo口语笔记(35) - 常见单词结尾发音
- Creole
Home Bisher besucht: AnzeigenAnhängeInfo The Creole 1.0 project has been succ ...
- Wiki知识介绍
Wiki简介 Wiki一词来源于夏威夷语的“wee kee wee kee”,原本是“快点快点”的意思,被译为“维基”或“维客”.一种多人协作的写作工具.Wiki站点可以有多人(甚至任何访问者)维护, ...