题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035

题意:一棵树有n个点,每个点有自己的颜色,任意两个不同的点可以组成一条路径。也就是说一共有n(n-1)/2条不同的路径,每条路径的价值等于这条路径上颜色的数量,求所有路径的总价值。

思路:这道题采用补集的思想,我们假设总共有m个颜色出现,一共有n(n-1)/2条路径,我们假设每条路径都有m种颜色出现总价值就是m*n(n-1)/2。那么我们只要减去每种颜色在哪些路径中没有出现过,就可以得到答案。

具体做法:我们都下过围棋吧!我们把一棵树的点看成一个棋盘上棋子,被同颜色的棋子围在其中的点,和外面的点的所形成的路径都是要经过这种颜色的。而内部的点两两之间所形成的路径是不存在这种颜色,是我们需要减去的。

那么我们怎么得到这个被围在中间的点的数量呢?

题解中提到一个虚树思想。其实就是维护一个dfs过程中的值(用数组构造),在这里我们维护一个某一个颜色的dfs完返回到这个点的时候这个点下方与这个点颜色相同的点为根的子树大小。

我们现在开始模拟程序的过程。

对于1节点,5节点和6节点与它颜色相同,5节点为根的子树大小为3,6节点为根的子树大小也为3,那么实际上被围在中间的点就是1节点两个后续后续节点为根的子树大小(分别是2节点和3节点),我们把2节点为根的树的大小减去5节点为根数的大小得到2就是被1节点和5节点围在中间的点的个数。3节点为根的树的大小减去6节点为根的树的大小得到被1和6节点围在中间的点的个数。那么我们怎么得到5为根的点的个数和6为根点的个数呢?

我们dfs(左边先dfs)从1开始我们一路一下当前红色节点为根的子树大小为0,我们记录一个这个值s1,然后一路dfs到底然后返回,假设我们dfs返回到5的时候,我们已经知道5的大小是3,从而我们把sum[red]更新为3。然后返回到1,我们知道对1节点的2这个子树中红色颜色为根的最大子树大小为3(通过3-0),而2这个子树的带下为5,说明有两个点不是被围在中间。这个时候我们记录一个完成2子树这个支路我们已经把红色为根子树大小已经从0更新为3,把s1更新为3。

然后我们进入1的右子树3,一路dfs到底返回到6,假设我们知道6的带下是3,那么我们应该把sum[red]+=3=6,然后返回到1的时候我们发现sum[red]-s1=3,说明3这个支路下面有有一颗大小为3颜色是红色子树6。那么被围在中间的点就是3为根树的大小减去6为根子树的大小得到被围在中间的点为5-3=2

最后1也是一颗别人的子树,我们在返回的时候需要合并1这个节点下面所有红色节点为根的子树的和即5的大小3和6的大小3,加起来等于6,而1这个树本身的大小是11,所以对于整个sum[red]的增加量就是1为根的树的大小-6等于5,完了以后sum[red]=5+6=11等于1节点为根树的大小,再返回给1的祖先,同理我们从5和6节点那里得到他返回子树的大小也是通过同样类型的方式。这个可能就是所谓的虚树的应用吧!

代码:

 //Author: xiaowuga
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <map>
#include <bitset>
#include <cctype>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
#define mem(s,ch) memset(s,ch,sizeof(s))
#define da cout<<da<<endl
#define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
#define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
const long long N=+;
using namespace std;
typedef long long LL;
LL sum[N],sz[N],col[N],vis[N];
//sz[i]代表以i节点为根的子树大小
//col[i]代表的是i节点的颜色
//我们通过vis数组判断是否出现过某种颜色,以便统计出现了多少种颜色
//sum数组有点难理解,sum[i]表示当前i颜色的子树大小之和(在深搜过程中会值会改变。)
vector<int>p[N];
LL cut=,n;
void init(){//初始化
for(int i=;i<=n;i++){
p[i].clear();
sum[i]=sz[i]=cut=vis[i]=;
}
}
void dfs(int u,int pre){
sz[u]=;
LL s=sum[col[u]];
LL step=;
for(int i=;i<p[u].size();i++){
LL v=p[u][i];
if(v==pre) continue;
LL s=sum[col[u]];//这个点进栈前该点颜色的树的大小
dfs(v,u);
sz[u]+=sz[v];//加上所有子树的大小计算以u点为根的树的大小
LL qr=sum[col[u]]-s;//qr代表这个子树下面的同颜色孙树的大小
step+=qr;//合并所有子树中同样颜色的孙树大小
LL szv=sz[v]-qr;//这个子树与同u点颜色相同的孙树之间点的数量
cut=cut+szv*(szv-)/;//计算不存在颜色u的路径数
}
sum[col[u]]+=sz[u]-step;
}
int main() {
ios::sync_with_stdio(false);cin.tie();
int ca=;
while(cin>>n){
init();
LL ct=;
for(int i=;i<=n;i++) {
cin>>col[i];
if(!vis[col[i]]){ct++; vis[col[i]]=;}
}
for(int i=;i<n-;i++){
int x,y;
cin>>x>>y;
p[x].push_back(y);
p[y].push_back(x);
}
dfs(,);
for(int i=;i<=n;i++){
if(vis[i]&&i!=col[]){
LL szv=n-sum[i];
cut=cut+szv*(szv-)/;
}
}
LL ans=n*(n-)/*ct;
cout<<"Case #"<<++ca<<": "<<ans-cut<<endl;
}
return ;
}

2017 Multi-University Training Contest - Team 1—HDU6035的更多相关文章

  1. 2017 Multi-University Training Contest - Team 9 1005&&HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】

    FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  2. 2017 Multi-University Training Contest - Team 9 1004&&HDU 6164 Dying Light【数学+模拟】

    Dying Light Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tot ...

  3. 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】

    CSGO Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  4. 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  5. 2017 Multi-University Training Contest - Team 9 1001&&HDU 6161 Big binary tree【树形dp+hash】

    Big binary tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  6. 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】

    Colorful Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  7. 2017 Multi-University Training Contest - Team 1 1006&&HDU 6038 Function【DFS+数论】

    Function Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...

  8. 2017 Multi-University Training Contest - Team 1 1002&&HDU 6034 Balala Power!【字符串,贪心+排序】

    Balala Power! Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  9. 2017 Multi-University Training Contest - Team 1 1011&&HDU 6043 KazaQ's Socks【规律题,数学,水】

    KazaQ's Socks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

随机推荐

  1. 【Android】13.4 使用SQLite.NET.Async-PCL访问SQLite数据库

    分类:C#.Android.VS2015: 创建日期:2016-02-27 一.简介 这一节演示如何利用以异步方式(async.await)访问SQLite数据库. 二.示例4运行截图 下面左图为初始 ...

  2. Struts2初学 struts2自定义类型转换器

    一.问题的引出      Struts2的类型转换是基于OGNL表达式的,由于请求的参数都是字符串,而JAVA 本身属于强类型的的语言,这样就需要把请求参数字符串转换成其他类型.     Struts ...

  3. 102. Linked List Cycle【medium】

    Given a linked list, determine if it has a cycle in it.   Example Given -21->10->4->5, tail ...

  4. CentOS 6.2下log4cplus的使用

    一.简介 log4cplus是一款优秀的基于C/C++的开源日志库.log4cplus具有线程安全,不用但心在多线程状态下写日志问题:使用灵活,可通过配置文件设置日志级别下输出位置,还可以在程序运行时 ...

  5. 一款基于jQuery的超酷动画幻灯片

    今天给大家带来一款仿步步高vivo手机网站的一款首页焦点幻灯展示特效,带有超酷炫的动画特效,动态效果丝毫不逊色于flash动画,具有很强的视觉冲击力,推荐下载学习! 提示:兼容360.FireFox. ...

  6. love2d教程30--文件系统

    在游戏里少不了文件操作,在love2d里我们可以直接用lua自带的io函数,如果不熟悉可以先读一下我的lua文件读写. 相对lua,love2d提供了更多的函数, 方便我们操作文件.不过可能处于安全考 ...

  7. 用newInstance与用new是区别的

    用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩.可扩展,可重用等软件思想上解释了.Java中工厂模式经 ...

  8. Mac CEF 支持mp3 mp4编译

    1.下载:https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding   差不多15G 2.编译:https://bitbu ...

  9. 【Debian】时间设置

    http://blog.linuxphp.org/archives/567/ http://www.dedecms.com/knowledge/servers/linux-bsd/2012/0819/ ...

  10. 用css制作星级评分

    Step 1: XHTML <ul class="star-rating">       <li><a href="#" titl ...