• hdu 6035(Colorful Tree)


    参考题解做的!思路+题意 在代码中藏着呢。

      1 #include <stdio.h>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <string.h>
      5 #include <math.h>
      6 #include <string>
      7 
      8 
      9 using namespace std;
     10 typedef long long int LL;
     11 const int MOD= 1e9+7;
     12 const int INF=2e9+1e8;
     13 
     14 
     15 const int maxn=200000+1000;
     16 /**
     17  * 数据定义部分
     18  */
     19 struct Node 
     20 {
     21     int to,next;
     22 }edge[maxn*2];
     23 int first[maxn],sz,color[maxn];
     24 
     25 void addedge(int s,int t)
     26 {
     27     edge[sz].to=t,edge[sz].next=first[s];
     28     first[s]=sz++;
     29 }
     30 
     31 LL cnt;
     32 LL size[maxn],sum[maxn];
     33 /**
     34  * sum[i] 是一个维护的数组,表示当前i颜色的此时i颜色为子树的根的子树的大小;
     35  */
     36 void dfs(int x,int pre)
     37 {
     38     size[x]=1;
     39     int all=0;
     40     int last=sum[color[x]];
     41     for(int i=first[x];i!=-1;i=edge[i].next)
     42     {
     43         int to=edge[i].to;
     44         if(to==pre) continue;
     45         dfs(to,x);
     46         size[x]+=size[to];
     47         LL delta=sum[color[x]]-last;//delta 是变化量
     48         LL tmp=size[to]-delta;//子树大小-变化量 就是 子树联通块大小;
     49         last=sum[color[x]];
     50         cnt+=tmp*(tmp-1)/2;
     51         all+=size[to]-delta;
     52     }
     53     sum[color[x]]+=all+1;
     54 }
     55 /**
     56  * 题目意思:给定一棵树,树节点编号为1~n,树上的节点有颜色,颜色范围也是1~n。
     57  * 定义一个值:树上任意不同两个节点路径上的不同颜色的个数(也就是颜色的种类数)。
     58  * 求所有的任意两个点的这个值的和是多少?有n*(n-1)/2种值,需要加起来。
     59  * 
     60  * 大致思路:求不同路径的颜色种类和;
     61  * 对于每种颜色考虑:有多少条路径含有这种颜色,再把每种颜色的加起来就是
     62  * 最终答案;
     63  * 反过来思考颜色:有多少条路径不包含这种颜色,求和,假设求和后值为 sum。
     64  * 那么最终答案就是:颜色总共的种类数×(n*(n-1)/2)-sum;
     65  * 那么sum怎么求?我们先只考虑一种颜色,我们考虑的颜色这个点会将树分割开成多个子树,
     66  * 多个子树内部之间路径是不包含这种颜色的;dfs子树节的时候,遇到的节点颜色就是需要处理的
     67  * 每个子树的路径数量:假设这个子树有k个节点,那么就是k*(k-1)/2;
     68  */
     69 
     70  /**
     71   * 代码具体实现:
     72   * size[i]代表i号节点的子树的节点数量,
     73   */
     74 
     75 int vis[maxn];
     76 int main()
     77 {
     78     int cas=1,n;
     79     while(scanf("%d",&n)+1)
     80     {
     81         LL total=0;
     82         memset(vis,0,sizeof(vis));
     83         sz=0;
     84         memset(first,-1,sizeof(first));
     85         memset(sum,0,sizeof(sum));
     86         for(int i=1;i<=n;i++) 
     87         {
     88             scanf("%d",&color[i]);
     89             if(vis[color[i]]==0)
     90             {
     91                 total++;
     92                 vis[color[i]]=1;
     93             }
     94         }
     95         for(int i=1;i<n;i++)
     96         {
     97             int x,y;
     98             scanf("%d%d",&x,&y);
     99             addedge(x,y);
    100             addedge(y,x);
    101         }
    102         cnt=0;
    103         dfs(1,1);
    104         for(int i=1;i<=n;i++)
    105         {
    106             if(vis[i]&&i!=color[1])
    107             {
    108                 LL  temp=n-sum[i];
    109                 cnt+=temp*(temp-1)/2;
    110             }
    111         }
    112         printf("Case #%d: %lld
    ",cas++,total*n*(n-1)/2-cnt);
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    安全加固3-加固
    Centos7 64位 -- glibc-2.29 编译升级方法(已成功)
    Centos7 -- glibc 升级失败、意外删除、故意删除后的处理方法
    系统引导修复,grub2下的各种骚作
    linux 升级 5.0.2内核
    kvm虚拟化二: 字符界面管理及 无人值守安装
    kvm虚拟化一: 图形化的管理方式
    Linux rhel7 无线网络配置
    虚拟化简介
    requests模块使用二
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7243110.html
Copyright © 2020-2023  润新知