zoukankan      html  css  js  c++  java
  • hdu 6035(树形dp)

    题意:给你棵树,树上每个节点都有颜色,每条路径上有m种颜色  问你所有路径上出现的颜色的和

    思路:答案求的是每种颜色对路径的贡献  我们可以反过来每种颜色不经过的路径的条数

    假设根节点的颜色为x  我们就可以知道不过x颜色的路径一定不经过这个根节点 和不经过这个子树中颜色为x的节点

    所有树形dp。。。。。。。

    son[u]统计的是以u的根节点的子树的大小  节点的颜色为a[i]   sum[a[i]]为在以i节点为根节点颜色a[i]的子树大小, 比如 1 8节点的颜色相同  x颜色没有经过的节点为1的儿子-sum[a[8]];

    sum[a[8]]是可以在DFS中过程得到的 没有经过的点有y个  路径就有y*(y-1)/2;

    所有我们在DFS一遍就能求出所有颜色没有经过的路径数目

    答案就是所有的颜色经过所有的路径-所有的点没有经过的路径数目

    我感觉dfs解释的有点牵强  具体看代码把 比较好理解

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<string.h>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<stack>
    11 #include<map>
    12 #include<cmath>
    13 typedef long long ll;
    14 typedef unsigned long long LL;
    15 using namespace std;
    16 const double PI=acos(-1.0);
    17 const double eps=0.0000000001;
    18 const int N=500000+100;
    19 int a[N],b[N];
    20 int n,m;
    21 int tot;
    22 int head[N];
    23 ll ans;
    24 int son[N];
    25 int sum[N];
    26 struct node{
    27     int to,next;
    28 }edge[N<<1];
    29 void init(){
    30     memset(head,-1,sizeof(head));
    31     memset(sum,0,sizeof(sum));
    32     tot=0;
    33 }
    34 void add(int u,int v){
    35     edge[tot].to=v;
    36     edge[tot].next=head[u];
    37     head[u]=tot++;
    38 }
    39 void DFS(int u,int fa){
    40     son[u]=1;
    41     ll t=sum[a[u]];
    42     ll c=0;
    43     for(int i=head[u];i!=-1;i=edge[i].next){
    44         int v=edge[i].to;
    45         if(v==fa)continue;
    46         DFS(v,u);
    47         son[u]=son[v]+son[u];
    48         ll temp=son[v]-(sum[a[u]]-t);
    49         t=sum[a[u]];
    50         c=c+temp;
    51         ans=ans-(temp-1)*temp/2;
    52     }
    53     sum[a[u]]+=c+1;
    54 }
    55 int main(){
    56     int tt=1;
    57     while(scanf("%d",&n)!=EOF){
    58         init();
    59         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    60         for(int i=1;i<n;i++){
    61             int u,v;
    62             scanf("%d%d",&u,&v);
    63             add(u,v);
    64             add(v,u);
    65         }
    66         ans=(ll)n*(n-1)*n/2;
    67         DFS(1,0);
    68         for(int i=1;i<=n;i++){
    69             ll temp=n-sum[i];
    70             ans=ans-(temp-1)*temp/2;
    71         }
    72         printf("Case #%d: %lld
    ", tt++, ans);
    73     }
    74 }
  • 相关阅读:
    js运算符逻辑!和instanceof的优先级
    一道关于数组的前端面试题
    关于变量提升
    关于offsetParent
    获取地址栏的参数列表,并转化为对象
    关于类型转换
    bootstrap-4
    bootstrap-3
    bootStrap-2
    bootStrap-1
  • 原文地址:https://www.cnblogs.com/Aa1039510121/p/7711396.html
Copyright © 2011-2022 走看看