zoukankan      html  css  js  c++  java
  • 【hdu6035】 Colorful Tree dfs序

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6035

    题目大意:给你一棵树,树上每个节点都有一个颜色。 现在定义两点间的距离为两点最短路径上颜色集合大小,求该树上所有点对的距离之和。其中树上的节点个数$≤2*10^5$

    如果直接处理每一条路径上颜色集合大小,显然比较麻烦。我们不妨换一种思路。

    我们用S_i表示经过颜色i的路径的数量,显然答案$=sum S_i$。

    考虑如何求S_i。我们先将所有颜色为i的节点全部找出来,按照dfs序排序。

    显然,若树上所有的路径均经过该颜色的节点,则$S_i=frac{n*(n-1)}{2}$。

    对于该点集中的节点x的每一棵子树,不妨设当前子树的根节点为v,找出所有点集中满足$dfn[v]<dfn[u]≤low[v]$且不存在$y$,使得$dfn[v]<dfn[y]<dfn[u]≤low[v]$的所有的$u$,则显然有$frac{(siz[v]-sum siz[u]) imes (siz[v]-sum siz[u]-1)}{2}$个点对不会对答案产生贡献。其中$siz[x]$表示以x为根的子树的节点个数。

    该统计方法的时间复杂度为$O(n log n)$

     1 #include<bits/stdc++.h>
     2 #define L long long
     3 #define M 200005
     4 using namespace std;
     5 struct edge{int u,next;}e[M*2]={0}; int head[M]={0},use=0;
     6 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
     7 
     8 int dfn[M]={0},low[M]={0},t=0;
     9 int siz[M]={0},col[M]={0}; 
    10 
    11 void dfss(int x,int fa){
    12     dfn[x]=++t; siz[x]=1;
    13     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
    14         dfss(e[i].u,x);
    15         siz[x]+=siz[e[i].u];
    16     }
    17     low[x]=t;
    18 }
    19 bool cmp(int x,int y){
    20     if(col[x]==col[y]) return dfn[x]<dfn[y];
    21     return col[x]<col[y];
    22 }
    23 int p[M]={0};
    24 L ans=0,sum=0,n;
    25 
    26 void dfs(int &x,int y){
    27     int xx=p[x]; x++;
    28     for(int i=head[xx];i;i=e[i].next)
    29     if(dfn[xx]<dfn[e[i].u]){
    30         int v=e[i].u;
    31         L cnt=siz[v];
    32         while(x<=y&&dfn[p[x]]<=low[v]){
    33             cnt-=siz[p[x]];
    34             dfs(x,y);
    35         }
    36         sum-=cnt*(cnt-1);
    37     }
    38 }
    39 int hh=0;
    40 int Main(){
    41     hh++;
    42     ans=0; sum=0; t=0;
    43     memset(head,0,sizeof(head)); use=0;
    44     for(int i=1;i<=n;i++) scanf("%d",col+i);
    45     for(int i=1;i<n;i++){
    46         int x,y; scanf("%d%d",&x,&y);
    47         add(x,y); add(y,x);
    48     }
    49     dfss(1,0); add(0,1);
    50     for(int i=1;i<=n;i++) p[i]=i;
    51     sort(p+1,p+n+1,cmp);
    52     for(int i=1,j;i<=n;i=j+1){
    53         for(j=i;col[p[i]]==col[p[j]];j++); j--;
    54         sum=n*(n-1);
    55         p[--i]=0;
    56         dfs(i,j);
    57         ans+=sum;
    58     }
    59     printf("Case #%d: %lld
    ",hh,ans/2);
    60     //cout<<ans/2<<endl;
    61 }
    62 
    63 int main(){
    64     freopen("in.txt","r",stdin);
    65     while(cin>>n) Main();
    66 }
  • 相关阅读:
    php中常用的字符串函数,大全了
    php写的验证码实现方法
    简单的php做的一个验证码生成方案
    ActiveMQ+SpringMVC+Maven应用示例
    zookeeper简单操作
    zookeeper基本概念及原理
    zookeeper 事务日志与快照日志
    activeMQ安装与测试
    activeMQ "HelloWorld"实现
    JMS基本概念
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/8879897.html
Copyright © 2011-2022 走看看