hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】
单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和。反过来思考只需要求有多少条路径没有经过这种颜色即可。
具体实现过程比较复杂,很神奇的一个树形dp,下面给出一个含较详细注释的代码及对应的一组自造的数据以及图片来进行解释
欢迎交流,给出意见~~~
数据
- /*
第二行的1 2 3在图中分别用红黄蓝来表示- 15
- 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
- 1 2
- 1 3
- 2 4
- 2 5
- 3 6
- 3 7
- 4 8
- 4 9
- 5 10
- 5 11
- 6 12
- 6 13
- 7 14
- 7 15
- */
含注释的代码
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long LL;
- const int N=2e5+;
- int n;
- int c[N]; //各结点的颜色
- int size[N]; //size[i]记录结点i的子树的大小,叶子为1
- int vis[N]; //vis[i]记录颜色i是否出现过
- int sum[N]; //见函数内注释及图片
- vector<int> adj[N];
- LL ans,de;
- LL C(LL a,LL b) //计算组合数,这样写是为了增加后面的代码的可读性
- {
- LL ret=;
- for(int i=;i<=b;i++)
- ret=ret*(a+-i)/i;
- return ret;
- }
- void dfs(int u,int pre)
- {
- // 定义 u 为“当前结点”
- // sum[c[u]]表示, 整棵树中,已经被dfs过的,
- // 与当前结点具有相同颜色的结点的所有子树的大小之和
- // 不重复计数
- // 图一展示了的是刚刚进入dfs(7,3)时sum[c[u]]包含的结点
- printf("\n\n==================================\nEnter->%d\n\n",u);
- int all=;
- size[u]=;
- for(int to:adj[u])
- {
- if(to==pre) continue;
- int sumu_bd=sum[c[u]]; //bd : before dfs
- //记录此次dfs前的sum[c[u]]
- dfs(to,u);
- size[u]+=size[to];
- int part=sum[c[u]]-sumu_bd; //dfs过后,sum[c[u]]会产生一个增量,用part来记录这个增量
- all+=part; //all用来记录,对u dfs的过程中,sum[c[u]]产生的总增量
- //这是在为 u返回pre时更新sum[c[u]]做准备
- printf("from %d return to %d\n",to,u);
- printf("all=%d,sumu_bd=%d,part=%d,sum[c[u]]=%d\n",all,sumu_bd,part,sum[c[u]]);
- printf("to=%d,size[to]=%d\n",to,size[to]);
- de+=C(size[to]-part,); //size[to]-part的含义: 在to为根节点的子树中,有一部分结点与to位于同一“块”,
- // 这个块以 与u颜色相同的结点(不含),或是叶子(含,若叶子与u颜色相同则不含) 为边界
- // size[to]-part表示的是这个块的大小
- // 图二展示了 dfs(1,0)内,刚刚执行完dfs(2,1)后,更新de时的size[2]-part
- printf("\nnow,de=%d\n\n",de);
- }
- printf("\n\n=== leaving... ===\n\n");
- printf("pre_sum[c[u]]=%d\n",sum[c[u]]);
- sum[c[u]]+=size[u]-all;
- printf("after_sum[c[u]]=%d\n",sum[c[u]]);
- printf("\nleave from %d\n\n==================================\n\n",u);
- }
- int main()
- {
- int kase=;
- while(~scanf("%d",&n))
- {
- memset(vis,,sizeof(vis));
- memset(size,,sizeof(size));
- memset(sum,,sizeof(sum));
- for(int i=;i<=n;i++) adj[i].clear();
- int c_num=;
- de=;
- for(int i=;i<=n;i++)
- {
- scanf("%d",&c[i]);
- if(!vis[c[i]]) c_num++;
- vis[c[i]]=;
- }
- for(int i=;i<n;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- adj[u].push_back(v);
- adj[v].push_back(u);
- }
- dfs(,);
- for(int i=;i<=n;i++)
- if(i!=c[]&&vis[i]) de+=C(n-sum[i],);
- ans=C(n,)*c_num-de;
- printf("Case #%d: %lld\n",++kase,ans);
- }
- }
图一:
图二:
AC代码
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long LL;
- const int N=2e5+;
- int n;
- int c[N];
- int size[N];
- int vis[N];
- int sum[N];
- vector<int> adj[N];
- LL ans,de;
- LL C(LL a,LL b)
- {
- LL ret=;
- for(int i=;i<=b;i++)
- ret=ret*(a+-i)/i;
- return ret;
- }
- void dfs(int u,int pre)
- {
- int all=;
- size[u]=;
- for(int to:adj[u])
- {
- if(to==pre) continue;
- int sumu_bd=sum[c[u]];
- dfs(to,u);
- size[u]+=size[to];
- int part=sum[c[u]]-sumu_bd;
- all+=part;
- de+=C(size[to]-part,);
- }
- sum[c[u]]+=size[u]-all;
- }
- int main()
- {
- int kase=;
- while(~scanf("%d",&n))
- {
- memset(vis,,sizeof(vis));
- memset(size,,sizeof(size));
- memset(sum,,sizeof(sum));
- for(int i=;i<=n;i++) adj[i].clear();
- int c_num=;
- de=;
- for(int i=;i<=n;i++)
- {
- scanf("%d",&c[i]);
- if(!vis[c[i]]) c_num++;
- vis[c[i]]=;
- }
- for(int i=;i<n;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- adj[u].push_back(v);
- adj[v].push_back(u);
- }
- dfs(,);
- for(int i=;i<=n;i++)
- if(i!=c[]&&vis[i]) de+=C(n-sum[i],);
- ans=C(n,)*c_num-de;
- printf("Case #%d: %lld\n",++kase,ans);
- }
- }
简版的
hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】的更多相关文章
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- hdu 6044 : Limited Permutation (2017 多校第一场 1012) 【输入挂 组合数学】
题目链接 参考博客: http://blog.csdn.net/jinglinxiao/article/details/76165353 http://blog.csdn.net/qq_3175920 ...
- hdu 6047: Maximum Sequence (2017 多校第二场 1003)【贪心】
题目链接 可以贪心写,先把b数组按从小到大的顺序排个序,根据b[i]的值来产生a[n+i] 借助一个c数组,c[i]记录,j从i到n,a[j]-j的最大值,再加上一个实时更新的变量ma,记录从n+1到 ...
- 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 ...
- 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)
题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...
- HDU-6035 Colorful Tree(树形DP) 2017多校第一场
题意:给出一棵树,树上的每个节点都有一个颜色,定义一种值为两点之间路径中不同颜色的个数,然后一棵树有n*(n-1)/2条 路径,求所有的路径的值加起来是多少. 思路:比赛的时候感觉是树形DP,但是脑袋 ...
- HDU 6035 Colorful Tree(补集思想+树形DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 单独考虑 ...
- HDU 6035 Colorful Tree (树形DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 我们计算 ...
- HDU 6035 Colorful Tree(dfs)
题意:一棵有n个点的树,树上每个点都有颜色c[i],定义每条路径的值为这条路径上经过的不同颜色数量和.求所有路径的值的和. 可以把问题转化为对每种颜色有多少条不同的路径至少经过这种颜色的点,然后加和. ...
随机推荐
- weight(搜索对象的选取)
题目链接: 就是大概这么个东西 根据题意,我们可以清楚的知道:这个题我不会,这个题需要先将2n个数进行排序 这样每对于一个小的前(后)缀和总会在队列最前或队列最后 设这个数为k 那么判断总的Sum(n ...
- Gitblit 添加密钥实现客户端无密码pull、push代码
之前管理代码用的是SVN,项目需要将管理代码软件切换为Git 折腾了一天,记录下遇到的小坑,方便后来人. 服务端 服务端 的系统是Windows Sever2008 ,首先在服务端安装window版本 ...
- CSS - 视觉格式化模型(Visual formatting model)
几个概念 块:block,一个抽象的概念,块与块之间在垂直方向上按照顺序依次堆叠. 行内:inline,一个抽象的概念,行内与行内之间在水平方向上按照顺序依次堆叠(会有换行). 元素:element, ...
- 再谈 COW、ROW 快照技术
目录 目录 前言 快照与备份的区别 快照技术 增量快照之 COW 增量快照之 row 前言 在经过了一段时间的实践之后,再次回顾 COW/ROW 快照技术的实现原理,温故而知新. 快照与备份的区别 传 ...
- VMware 接入 Openstack — 使用 Openstack 创建 vCenter 虚拟机
目录 目录 软件环境 前言 Openstack 接口驱动 使用 KVM 在 Compute Node 上创建虚拟机的流程 使用 VCDirver 在 vCenter 上创建虚拟机的流程 配置 vCen ...
- list数据的存储
1 存储成csv格式 简单方法: a = [3,3,4,4] df = {'a': a} df = pd.DataFrame(df) df.to_csv('./a.csv') 复杂方法: import ...
- QTP 11 补丁大全
原文: http://relevantcodes.com/qtp-11-0-patches/ Patch Link Details Support for Chrome 19 QTPWEB_00102 ...
- DP---DAG、背包、LIS、LCS
DP是真的难啊,感觉始终不入门路,还是太弱了┭┮﹏┭┮ DAG上的DP 一般而言,题目中如果存在明显的严格偏序关系,并且求依靠此关系的最大/最小值,那么考虑是求DAG上的最短路或者是最长路.(据说 ...
- 20191003 尚硅谷Spring Cloud教学视频
视频信息 视频日期:2018-4-19 讲师:尚硅谷周阳 Spring Cloud版本:Dalston.RELEASE 当前版本:Greenwich SR3 微服务.微服务架构.Spring Clou ...
- python基础-6 正则表达式
一 python正则简介 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现. 正则表达式模式被编译成一系列的字 ...