【hdu6035】 Colorful Tree dfs序

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6035

题目大意:给你一棵树,树上每个节点都有一个颜色。 现在定义两点间的距离为两点最短路径上颜色集合大小,求该树上所有点对的距离之和。其中树上的节点个数$≤2*10^5$

如果直接处理每一条路径上颜色集合大小,显然比较麻烦。我们不妨换一种思路。

我们用S_i表示经过颜色i的路径的数量,显然答案$=\sum S_i$。

考虑如何求S_i。我们先将所有颜色为i的节点全部找出来,按照dfs序排序。

显然,若树上所有的路径均经过该颜色的节点,则$S_i=\frac{n*(n-1)}{2}$。

对于该点集中的节点x的每一棵子树,不妨设当前子树的根节点为v,找出所有点集中满足$dfn[v]<dfn[u]≤low[v]$且不存在$y$,使得$dfn[v]<dfn[y]<dfn[u]≤low[v]$的所有的$u$,则显然有$\frac{(siz[v]-\sum siz[u]) \times (siz[v]-\sum siz[u]-1)}{2}$个点对不会对答案产生贡献。其中$siz[x]$表示以x为根的子树的节点个数。

该统计方法的时间复杂度为$O(n log n)$

 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define M 200005
 4 using namespace std;
 5 struct edge{int u,next;}e[M*2]={0}; int head[M]={0},use=0;
 6 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
 7
 8 int dfn[M]={0},low[M]={0},t=0;
 9 int siz[M]={0},col[M]={0};
10
11 void dfss(int x,int fa){
12     dfn[x]=++t; siz[x]=1;
13     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
14         dfss(e[i].u,x);
15         siz[x]+=siz[e[i].u];
16     }
17     low[x]=t;
18 }
19 bool cmp(int x,int y){
20     if(col[x]==col[y]) return dfn[x]<dfn[y];
21     return col[x]<col[y];
22 }
23 int p[M]={0};
24 L ans=0,sum=0,n;
25
26 void dfs(int &x,int y){
27     int xx=p[x]; x++;
28     for(int i=head[xx];i;i=e[i].next)
29     if(dfn[xx]<dfn[e[i].u]){
30         int v=e[i].u;
31         L cnt=siz[v];
32         while(x<=y&&dfn[p[x]]<=low[v]){
33             cnt-=siz[p[x]];
34             dfs(x,y);
35         }
36         sum-=cnt*(cnt-1);
37     }
38 }
39 int hh=0;
40 int Main(){
41     hh++;
42     ans=0; sum=0; t=0;
43     memset(head,0,sizeof(head)); use=0;
44     for(int i=1;i<=n;i++) scanf("%d",col+i);
45     for(int i=1;i<n;i++){
46         int x,y; scanf("%d%d",&x,&y);
47         add(x,y); add(y,x);
48     }
49     dfss(1,0); add(0,1);
50     for(int i=1;i<=n;i++) p[i]=i;
51     sort(p+1,p+n+1,cmp);
52     for(int i=1,j;i<=n;i=j+1){
53         for(j=i;col[p[i]]==col[p[j]];j++); j--;
54         sum=n*(n-1);
55         p[--i]=0;
56         dfs(i,j);
57         ans+=sum;
58     }
59     printf("Case #%d: %lld\n",hh,ans/2);
60     //cout<<ans/2<<endl;
61 }
62
63 int main(){
64     freopen("in.txt","r",stdin);
65     while(cin>>n) Main();
66 }

原文地址:https://www.cnblogs.com/xiefengze1/p/8879897.html

时间: 2024-11-09 01:44:02

【hdu6035】 Colorful Tree dfs序的相关文章

hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定义每条路径的值为经过的节点的不同颜色数.求所有路径的值和. 思路:看题解后,才想出来的.树形dp. 求所有路径的值和 = 路径条数*总颜色数(n*(n-1)*colors/2)-sigma(每种颜色没有经过的路径条数) 主要是求每种颜色没有经过的路径条数. 画一棵树,我直接用颜色值表示节点编号. 2

[poj3321]Apple Tree(dfs序+树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26762   Accepted: 7947 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

hdu 6191 Query on A Tree(dfs序+可持久化字典树)

题目链接:hdu 6191 Query on A Tree 题意: 给你一棵树,每个节点有一个值,现在有q个询问,每个询问 询问一个u x,问以u为根的子树中,找一个节点,使得这个节点的值与x异或的值最大,输出那个最大的值. 题解: dfs序和一棵可持久化字典树就搞定了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

POJ3321 - Apple Tree DFS序 + 线段树或树状数组

Apple Tree:http://poj.org/problem?id=3321 题意: 告诉你一棵树,每棵树开始每个点上都有一个苹果,有两种操作,一种是计算以x为根的树上有几个苹果,一种是转换x这个点上的苹果,就是有就去掉,没有就加上. 思路: 先对树求一遍dfs序,每个点保存一个l,r.l是最早到这个点的时间戳,r是这个点子树中的最大时间戳,这样就转化为区间问题,可以用树状数组,或线段树维护区间的和. #include <algorithm> #include <iterator&

1076E/Educational Codeforces Round 54-E. Vasya and a Tree&lt;&lt;dfs序 树状数组

题意 给定一棵树,初始每个节点权值为零,q次更改,每次修改将以v为顶点的深度为d的子树全部加上x,最后输出所有节点的权重. 思路 题目只要求每个点最后的值,那么经过观察,发现一个点最后的权值大小只与他的父节点的更新有关,那么我们就只需要考虑他的父节点到他这条链上的情况,把这条链拿出来成为线段,然后维护后缀和就能得到此点上的权值.每个节点的贡献为给$[h,h+d]$增加$x$,所以维护时,只要在$h+d$点上加上$x$即可. 但是问题考察的是一棵树,我们就需要动态来完成这条链,我们采用dfs序去扫

HDU 5156 - Harry and Christmas tree (dfs序+离线树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=5156 BC#25的C题. 题意是:给出一颗大小为n的树,以1为根,然后给出m次染色,每次将节点u加上一种颜色(一个节点可以有多个颜色). 最后查询树上每个节点对应子树上包含的不同颜色数量. 当时这场比赛没有做,回来看一下题目,没看标解就试着敲了一遍,于是解题思路从一开始就走上了不归路. 标解是O(n+m)的方法,主要思路是将问题转为:一次染色表示将u到根节点的路径都染上这种颜色. 但这样做需要去重,因为如果u

POJ 3321 Apple Tree DFS序 + 树状数组

多次修改一棵树节点的值,或者询问当前这个节点的子树所有节点权值总和. 首先预处理出DFS序L[i]和R[i] 把问题转化为区间查询总和问题.单点修改,区间查询,树状数组即可. 注意修改的时候也要按照dfs序修改,因为你查询就是按照dfs查的,所以修改也要用dfs序修改 L[i]是唯一的. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <

codechef T6 Pishty and tree dfs序+线段树

PSHTTR: Pishty 和城堡题目描述 Pishty 是生活在胡斯特市的一个小男孩.胡斯特是胡克兰境内的一个古城,以其中世纪风格 的古堡和非常聪明的熊闻名全国. 胡斯特的镇城之宝是就是这么一座古堡,历史上胡斯特依靠这座古堡抵挡住了疯人国的大军. 对于 Pishty 来说,真正吸引他的是古堡悠长的走廊和高耸的钟楼,以及深藏于其中的秘密-- 古堡可以用一棵 N 个节点的树的描述,树中有 N ?1 条无向边,每条边有一个魔法数字 C. 当一个旅游团参观古堡时,他们会选择树上 U 到 V 的路径游