HDU 4303 Hourai Jeweled 解题报告

评测地址: http://acm.hdu.edu.cn/showproblem.php?pid=4303

评测地址: https://xoj.red/contests/view/1155/1

题目描述

Kaguya Houraisan was once a princess of the Lunarians, a race of people living on the Moon. She was exiled to Earth over a thousand years ago for the crime of using the forbidden Hourai Elixir to make herself immortal. Tales of her unearthly beauty led men from all across the land to seek her hand in marriage, but none could successfully complete her trial of the Five Impossible Requests.

One of these requests is to reckon the value of "Hourai Jeweled (蓬莱の玉の枝)". The only one real treasure Kaguya has, in her possession. As showed in the picture, Hourai Jeweled is a tree-shaped twig. In which, each node is ornamented with a valuable diamond and each edge is painted with a briliant color (only bright man can distinguish the difference). Due to lunarians' eccentric taste, the value of this treasure is calculated as all the gorgeous roads' value it has. The road between two different nodes is said to be gorgeous, if and only if all the adjacent edges in this road has diffenrent color. And the value of this road is the sum of all the nodes' through the road.

Given the value of each node and the color of each edge. Could you tell Kaguya the value of her Hourai Jeweled?

输入格式

Input

The input consists of several test cases.

The first line of each case contains one integer N (1 <= N <= 300000), which is the number of nodes in Hourai Jeweled.

The second line contains N integers, the i-th of which is Vi (1 <= Vi <= 100000), the value of node i.

Each of the next N-1 lines contains three space-separated integer X, Y and Z (1<=X,Y<=N, 1 <= Z <= 100000), which represent that there is an edge between X and Y painted with colour Z.

输出格式

Output

For each test case, output a line containing the value of Hourai Jeweled.

样例输入输出

Sample Input

6

6 2 3 7 1 4

1 2 1

1 3 2

1 4 3

2 5 1

2 6 2

Sample Output

134

Hint

样例解释

gorgeous roads are :

1-2               Value: 8

1-3               Value: 9

1-4         Value:13

1-2-6          Value:12

2-1-3         Value:11

2-1-4    Value:15

2-5         Value:3

2-6               Value:6

3-1-4             Value:16

3-1-2-6        Value:15

4-1-2-6        Value:19

5-2-6            Value:7

版权信息

Author

BUPT

Source

2012 Multi-University Training Contest 1

Recommend

zhuyuanchen520   |   We have carefully selected several similar problems for you:  4300 4301 4302 4308 4304

题目翻译

题目描述:

一棵N个点的树,树上每个点有点权,每条边有颜色。一条路径的权值是这条路径上所有点的点权和,一条合法的路径需要满足该路径上任意相邻的两条边颜色都不相同。问这棵树上所有合法路径的权值和是多少啊?(无向路径)

输入格式:

第一行一个整数N,代表树上有多少个点。

接下来一行N个整数,代表树上每个点的权值。

接下来N-1行,每行三个整数S、E、C,代表S与E之间有一条颜色为C的边

输出格式:

一行一个整数,代表所求的值。

数据范围:

对与30%的数据,1≤N≤1000。

对于另外20%的数据,可用的颜色数不超过1e9且随机数据。

对于另外20%的数据,树的形态为一条链。

对于100%的数据,1≤N≤3e5,可用的颜色数不超过1e9,所有点权的大小不超过1e5。

题目解析(sol)

解析

l  Sub1 对于30%的数据,1≤N≤1000。

暴力dfs枚举所有链

复杂度: O(n^2)

程序:见后附1

l  Sub2 对于另外20%的数据,树的形态为一条链。

线性dp。

设f[i]表示到第i位的路径总长度,显然singma{f[i]|1<=i<=n}就是答案

另外设cnt[i]表示第i个点计入几次。

初始值:f[1]=0,由题意可知一个点不算

转移:

若上一条链和这一条链颜色一样,

cnt[i]=1,就是说前面的都不可以走到这个点上。

f[i]=w[r[i-1]]+w[r[i]];

若上一条链和这一条颜色不一样,

cnt[i]=cnt[i-1]+1,前面的点都可以走到这个点上

f[i]=f[i-1]+cnt[i]*w[r[i]]+w[r[i-1]]

复杂度:对于链的数据O(n),对于树的数据O(n^2)

程序:(见后附1)

l  Sub3 100%树形dp+统计

考虑两种可能:1.儿子到父亲的一条链

2.儿子跨过父亲到儿子

对于每个节点我们记录两个值就是:

1.这个节点可用子路径数量num[]

2.以节点为子树根向下链所有路径总长度dp[]

在考虑儿子跨过父亲到儿子的情况下我们发现暴力枚举每一个儿子是会T的,想到用到mpnum[col]表示和父节点相邻边为col色的路径条数,mpdp表示子节点和父亲连边为col色的点权和。

把两种情况分开来考虑。

  1. 儿子到父亲的一条链:

Dp[u]=Dp[u]+Dp[v]+val[u]*num[v] (lastcolor != nowcolor)

Dp[u]=Dp[u] (lastcolor == nowcolor)

  1. 儿子跨过父亲到儿子

其中s_Dp表示子树的Dp[u]的和,Num[u]表示子树总的经过次数,Ans是答案

Temp+=Dp[v]*(sum_Num-mpnum[a[i].col])+Num[v]*(S_Dp-mpdp[a[i].col])

Ans+=temp/2;

程序:(见后附2)

程序(Sub1+Sub2 : 50pts)

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int MAXN=3e5 + ;
int w[MAXN],head[MAXN],n,ans=,tot=,tt=,r[MAXN],du[MAXN],f[MAXN];
int cnt[MAXN];
bool vis[MAXN];
struct rec{
int pre,to,col;
}a[MAXN];
struct cc{
int from,to,val,id;
}node[MAXN];
map<pair<int,int>,int>mp;
void adde(int u,int v,int col)
{
a[++tot].pre=head[u];
a[tot].to=v;
a[tot].col=col;
head[u]=tot;
}
void dfs(int u,int co,int sum)
{
vis[u]=true; sum+=w[u]; ans+=sum;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (vis[v]) continue;
if (co==a[i].col) continue;
dfs(v,a[i].col,sum);
}
}
void dfs2(int u)
{
r[++tt]=u; vis[u]=true;
for (int i=head[u];i;i=a[i].pre){
int v=a[i].to; if (vis[v]) continue;
dfs2(v);
}
}
void work()
{
memset(du,,sizeof(du));
for (int i=;i<=n;i++) scanf("%lld",&w[i]);
int u,v,col;
for (int i=;i<=n-;i++) {
scanf("%lld%lld%lld",&u,&v,&col);
adde(u,v,col); adde(v,u,col);
mp[make_pair(u,v)]=col;
mp[make_pair(v,u)]=col;
du[u]++,du[v]++;
}
int root=;
for (int i=;i<=n;i++)
if (du[i]==) { root=i; break;}
tt=; memset(vis,false,sizeof(vis));
dfs2(root);
f[]=; int lc=-;
for (int i=;i<=n;i++){
if (mp[make_pair(r[i-],r[i])]!=lc) {
cnt[i]=cnt[i-]+;
f[i]=f[i-]+w[r[i]]*cnt[i]+w[r[i-]];
}
else cnt[i]=,f[i]=w[r[i]]+w[r[i-]];
lc=mp[make_pair(r[i-],r[i])];
}
int ans=;
for (int i=;i<=n;i++) ans+=f[i];
printf("%lld\n",ans);
}
signed main()
{
scanf("%lld",&n);
if (n>) { work(); return ;}
int t=;
for (int i=;i<=n;i++) scanf("%lld",&w[i]),t+=w[i];
int u,v,col;
for (int i=;i<=n-;i++) {
scanf("%lld%lld%lld",&u,&v,&col);
adde(u,v,col); adde(v,u,col);
}
for (int i=;i<=n;i++) {
memset(vis,false,sizeof(vis));
dfs(i,-,);
}
ans=(ans-t)/;
printf("%lld\n",ans);
return ;
}

程序(Sub3: 100 pts)

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int MAXN=3e5+;
int n,val[MAXN],ans;
struct rec{
int pre,to,col;
}a[*MAXN];
int head[MAXN],tot=;
int num[MAXN],dp[MAXN];
void adde(int u,int v,int col)
{
a[++tot].pre=head[u];
a[tot].to=v;
a[tot].col=col;
head[u]=tot;
}
void dfs(int u,int fa,int lc)
{
num[u]=; dp[u]=val[u];
map<int,int> mpnum,mpdp;
int s_Num=,s_Dp=,t=;
for (int i=head[u];i;i=a[i].pre){
int v=a[i].to; if(v==fa) continue;
dfs(v,u,a[i].col);
t=dp[v]+val[u]*num[v];
if (a[i].col!=lc) {
num[u]+=num[v];
dp[u]+=t;
}
s_Num+=num[v];
s_Dp+=t;
mpnum[a[i].col]+=num[v];
mpdp[a[i].col]+=t;
}
ans+=s_Dp;
int temp=;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
temp+=dp[v]*(s_Num-mpnum[a[i].col])+num[v]*(s_Dp-mpdp[a[i].col]);
}
ans+=temp/;
}
signed main()
{
scanf("%lld",&n);
for (int i=;i<=n;i++) scanf("%lld",&val[i]);
int u,v,col;
for (int i=;i<=n-;i++) {
scanf("%lld%lld%lld",&u,&v,&col);
adde(u,v,col);
adde(v,u,col);
}
dfs(,,-);
printf("%lld\n",ans);
return ;
}

From:     HGOI

Name:ljc20020730

Date: 20181004

HDU 4303 Hourai Jeweled 解题报告的更多相关文章

  1. HDU 4303 Hourai Jeweled(树形DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4303 题意:给出一棵树,树上的每一个节点都有一个权值,每条边有一个颜色,如果一条路径上相邻边的颜色都是不同的,那 ...

  2. HDU 4303 Hourai Jeweled 树dp 所有权利和航点 dfs2次要

    意甲冠军: long long ans = 0; for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) ans += F(i, ...

  3. hdu 2544 最短路 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目意思:给出 n 个路口和 m 条路,每一条路需要 c 分钟走过.问从路口 1 到路口 n 需 ...

  4. ACM 杭电HDU 2084 数塔 [解题报告]

    数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  5. hdu 1972.Printer Queue 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1972 题目意思:需要模拟打印机打印.打印机里面有一些 job,每个job被赋予1-9的其中一个值,越大 ...

  6. hdu 1014.Uniform Generator 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1014 题目意思:给出 STEP 和 MOD,然后根据这个公式:seed(x+1) = [seed(x) ...

  7. hdu 1098 Lowest Bit 解题报告

    题目链接:http://code.hdu.edu.cn/game/entry/problem/show.php?chapterid=1&sectionid=2&problemid=22 ...

  8. hdu 1232 畅通工程 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232 并查集入门题.最近在学并查集,它无非包括三个操作:make_set(x).union_set(x ...

  9. hdu 1050 Moving Tables 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1050 这道题目隔了很久才做出来的.一开始把判断走廊有重叠的算法都想错了.以为重叠只要满足,下一次mov ...

随机推荐

  1. Java基础—面向对象

    一.什么叫面向对象 万物皆对象(待更正) 二.面向对象三大特征 抽象:把一类对象共同特征进行抽取构造类的过程,包括两种抽象:第一种是数据抽象,也就是对象的属性.第二种是过程抽象,也就是对象的行为 封装 ...

  2. Latex数学公式编写

    小叙闲言 一直想用latex来编辑文档,但是没有需求,所以也没有去学习一下,但是最近由于要大量敲数学公式,有了latex数学公式的需求,所以来稍稍总结学习一下 1.在MathType中编写Latex数 ...

  3. 列表生成式+过滤器(filter)+映射(map)+lambda总结

    这些都是python的特色,不仅强大,而且好用,配合起来使用更是无敌. 零.lambda lambda用于产生一个匿名表达式,组成部分为:lambda + ‘函数表达式’ ‘函数表达式’由一个冒号加上 ...

  4. springboot打包成war后部署项目出现异常 LifecycleException: Failed to start component

    完整异常:org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].Sta ...

  5. [CF1038F]Wrap Around[AC自动机+dp]

    题意 题目链接 分析 题意容易转化成求循环之后不包含 \(s\) 的串的个数. 首先建立 AC 自动机.考虑一个暴力的做法:枚举长度为 \(n\) 的字符串 \(t\) 最终(后缀) 和 \(s\) ...

  6. Android Studio Xposed模块编写(一)

    1.环境说明 本文主要参考https://my.oschina.net/wisedream/blog/471292?fromerr=rNPFQidG的内容,自己实现了一遍,侵权请告知 已经安装xpos ...

  7. python代码实现经典排序算法

    排序算法在程序中有至关重要的作用, 不同算法的时间复杂度和空间复杂度都有所区别, 这影响着程序运行的效率和资源占用的情况, 经常对一些算法多加练习, 强化吸收, 可以提高对算法的理解, 进而运用到实践 ...

  8. C++基础知识(1)

    C语言是结构化编程语言(for循环.while循环.do while循环和if else语句),将低级语言的效率.硬件访问能力和高级语言的通用性.可移植性融合在一起. UNIX编译和链接 UNIX用C ...

  9. A - 摆仙果

    题目描述 Adrian, Bruno与Goran三人参加了仙界的宴会,宴会开始之前先准备了一些仙果供三人品尝,但是仙果的摆放有顺序要求,如果把仙果摆错了位置,仙果就会消失而无法品尝到. 由于三人是第一 ...

  10. LeetCode 88. 合并两个有序数组

    题目: 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m ...