zoukankan      html  css  js  c++  java
  • 洛谷5588 小猪佩奇爬树

    题目描述

    佩奇和乔治在爬♂树。

    给定 nn 个节点的树 T(V,E)T(V,E),第 ii 个节点的颜色为 w_iwi,保证有1 leq w_i leq n1win。

    对于1 leq i leq n1in,分别输出有多少对点对 (u,v)(u,v),满足 u<vu<v,且恰好经过所有颜色为 ii 的节点,对于节点颜色不为 ii 的其他节点,经过或不经过均可。

    树上路径 (u,v)(u,v) 定义为序列 {f}{f},满足 f_1=u,f_{|f|}=vf1=u,ff=v,且 forall 1 leq i < |f|1i<f∣,TT 中均存在边 (f_i,f_{i+1})(fi,fi+1),且 {f}{f} 中无重复元素,能够证明对于任意点对 (u,v)(u,v),其树上路径唯一。

    输入格式

    第一行 11 个正整数,表示 nn 。

    第二行 nn 个正整数,第 ii 个正整数表示 w_iwi

    之后 n-1n1 行,每行 22 个正整数 u,vu,v,表示 TT 中存在边 (u,v)(u,v)。

    输出格式

    共 nn 行,每行 11 个正整数,第 ii 行输出包含所有颜色为 ii 的节点的路径个数。

    输入输出样例

    输入 #1
    4
    1 2 2 3
    1 2
    2 3
    3 4
    输出 #1
    3
    4
    3
    6
    输入 #2
    10
    9 7 4 2 3 4 4 5 8 5
    2 1
    3 2
    4 2
    5 2
    6 4
    7 4
    8 1
    9 4
    10 4
    输出 #2
    45
    35
    9
    0
    1
    45
    34
    9
    17
    45

    说明/提示

    对于第一组样例而言。

    对于颜色 11,点对 (1,2),(1,3),(1,4)(1,2),(1,3),(1,4) 满足条件。

    对于颜色 22,点对 (1,3),(1,4),(2,3),(2,4)(1,3),(1,4),(2,3),(2,4) 满足条件。

    对于颜色 33,点对 (1,4),(2,4),(3,4)(1,4),(2,4),(3,4) 满足条件。

    对于颜色 44,由于图中没有颜色为 44 的节点,所以所有点对均满足条件。

    数据范围

    对于 40\%40% 的数据, n leq 10^2n102

    对于 60\%60% 的数据, n leq 10^3n103

    对于 100\%100% 的数据, n leq 10^6n106

    ——————————————————————————

    代码是自己写的,思路是哔哩哔哩上一个高手讲的!

    第一次发现搜索还可以这样用,不多见!也不好写!这是我在一个搜索中维护东西最多的一次!应该是!

    高手的讲解:https://www.bilibili.com/video/av74020427/

    ——————————————————————————

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e6+10;
     4 struct edge
     5 {
     6     int u,v,nxt;
     7 }e[maxn<<1];
     8 int head[maxn],js;
     9 int c[maxn],n;
    10 void addage(int u,int v)
    11 {
    12     e[++js].u=u;e[js].v=v;
    13     e[js].nxt=head[u];head[u]=js;
    14 }
    15 int zz[maxn],l[maxn],r[maxn],cnt[maxn],dfn[maxn],ct[maxn],siz[maxn],fat[maxn];
    16 int jss;
    17 int f[maxn][21],dep[maxn];
    18 void dfs(int u,int fa)
    19 {
    20     siz[u]=1;fat[u]=fa;
    21     dfn[u]=++jss;dep[u]=dep[fa]+1;f[u][0]=fa;
    22     for(int i=1;f[u][i-1];++i)f[u][i]=f[f[u][i-1]][i-1];
    23     if(zz[c[u]]&&dfn[u]>zz[c[u]])ct[c[u]]++;
    24     for(int i=head[u];i;i=e[i].nxt)
    25     {
    26         int v=e[i].v;
    27         if(v!=fa)
    28         {
    29             dfs(v,u);
    30             siz[u]+=siz[v];
    31         }
    32     }
    33     if(zz[c[u]]==0)zz[c[u]]=dfn[u],l[c[u]]=u;
    34     if(dfn[u]<=zz[c[u]])ct[c[u]]++;
    35     if(ct[c[u]]==cnt[c[u]])r[c[u]]=u;
    36     if(zz[c[u]]&&dfn[u]>zz[c[u]])ct[c[u]]--;
    37 }
    38 int lca(int u,int v)
    39 {
    40     if(dep[u]<dep[v])swap(u,v);
    41     for(int i=20;i>=0;--i)if(dep[f[u][i]]>=dep[v])u=f[u][i];
    42     if(u==v)return u;
    43     for(int i=20;i>=0;--i)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
    44     return f[u][0];
    45 }
    46 int main()
    47 {
    48     scanf("%d",&n);
    49     for(int i=1;i<=n;++i)scanf("%d",c+i),cnt[c[i]]++;
    50     for(int u,v,i=1;i<n;++i)
    51     {
    52         scanf("%d%d",&u,&v);
    53         addage(u,v);
    54         addage(v,u);
    55     }
    56     dfs(1,0);
    57     for(int i=1;i<=n;++i)
    58     {
    59         if(l[i]==0)printf("%lld
    ",(long long)n*(n-1)/2);
    60         else if(l[i]==r[i])
    61         {
    62             long long ans=2*n-2;
    63             int u=l[i];
    64             for(int i=head[u];i;i=e[i].nxt)
    65             {
    66                 int v=e[i].v;
    67                 if(v==fat[u])ans+=(long long)(n-siz[u])*(siz[u]-1);
    68                 else ans+=(long long)siz[v]*(n-siz[v]-1);
    69             }
    70             printf("%lld
    ",ans/2);
    71         }
    72         else if(r[i]==0)puts("0");
    73         else
    74         {
    75             long long ans;
    76             int tp=lca(l[i],r[i]);
    77             if(tp==l[i]||tp==r[i])
    78             {
    79                 if(tp!=l[i])swap(l[i],r[i]);
    80                 int x=r[i];
    81                 for(int j=20;j>=0;--j)if(dep[f[x][j]]>dep[l[i]])x=f[x][j];
    82                 ans=(long long)siz[r[i]]*(n-siz[x]);
    83             }
    84             else ans=(long long)siz[l[i]]*siz[r[i]];
    85             printf("%lld
    ",ans);
    86         }
    87     }        
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    数组中出现次数超过一半的数字
    字符串的排列(important)
    #pragma mark指令的作用
    类的声明和实现
    OC比C中,新增的数据类型
    NSLog (Log信息的输出)
    C语言中文件相关操作
    static 及 extern
    C语言预处理命令
    结构体
  • 原文地址:https://www.cnblogs.com/gryzy/p/14584871.html
Copyright © 2011-2022 走看看