• BZOJ1776: [Usaco2010 Hol]cowpol 奶牛政坛


    n<=100000个点的树,每个点属于一个K<=n/2个集合中的一个,每个集合至少两个点,求每个集合中任选两点距离的最大值。

    方法一:什么都看不出来,点分,每次只统计经过一个点的每个集合的不同子树的路径来更新。详见http://www.cnblogs.com/Enceladus/p/6099250.html腾爷好强!

    方法二:点分过程中我们每次只考虑来自根节点不同子树的最深的两个点来加,但如果所有同集合点都在一棵子树那答案就是最深到次深,也就是说不管怎么选最深都要选,不妨先把每个集合最深的点找出来直接lca找每个集合答案即可。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<math.h>
     5 //#include<iostream>
     6 using namespace std;
     7 
     8 int n,K;
     9 #define maxn 400011
    10 struct Edge{int to,next;};
    11 struct List{int id,next;}list[maxn];int first[maxn],li=2;
    12 int most[maxn],bel[maxn];
    13 struct Tree
    14 {
    15     Edge edge[maxn];
    16     int first[maxn],le,dis[maxn];
    17     Tree()
    18     {
    19         memset(first,0,sizeof(first));le=2;
    20         memset(dis,0,sizeof(dis));
    21     }
    22     void in(int x,int y)
    23     {
    24         edge[le].to=y;
    25         edge[le].next=first[x];
    26         first[x]=le++;
    27     }
    28     void insert(int x,int y)
    29     {
    30         in(x,y);
    31         in(y,x);
    32     }
    33     int f[maxn][22];
    34     void dfs(int x,int fa)
    35     {
    36         dis[x]=dis[fa]+1;f[x][0]=fa;
    37         if (dis[x]>dis[most[bel[x]]]) most[bel[x]]=x;
    38         for (int i=first[x];i;i=edge[i].next)
    39         {
    40             Edge &e=edge[i];
    41             if (e.to!=fa) dfs(e.to,x);
    42         }
    43     }
    44     void dfs() {dis[0]=0;dfs(1,0);}
    45     void pre()
    46     {
    47         for (int j=1;j<=20;j++)
    48             for (int i=1;i<=n;i++)
    49                 f[i][j]=f[f[i][j-1]][j-1];
    50     }
    51     int lca(int x,int y)
    52     {
    53         if (x==y) return x;
    54         if (dis[x]<dis[y]) {int t=x;x=y;y=t;}
    55         for (int j=20;j!=-1;j--) if (dis[f[x][j]]>=dis[y]) x=f[x][j];
    56         if (x==y) return x;
    57         for (int j=20;j!=-1;j--) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
    58         return f[x][0];
    59     }
    60 }t;
    61 int x;
    62 void in(int x,int y)
    63 {
    64     list[li].id=y;
    65     list[li].next=first[x];
    66     first[x]=li++;
    67 }
    68 int main()
    69 {
    70     scanf("%d%d",&n,&K);
    71     for (int i=1;i<=n;i++)
    72     {
    73         scanf("%d%d",&bel[i],&x);
    74         if (x) t.insert(x,i);
    75         in(bel[i],i);
    76     }
    77     memset(most,0,sizeof(most));
    78     t.dfs();
    79     t.pre();
    80     for (int i=1;i<=K;i++)
    81     {
    82         int ans=0;
    83         for (int j=first[i];j;j=list[j].next)
    84         {
    85             List &e=list[j];
    86             ans=max(ans,t.dis[e.id]+t.dis[most[i]]-2*t.dis[t.lca(e.id,most[i])]);
    87         }
    88         printf("%d
    ",ans);
    89     }
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    对象与内存控制1---实例变量和类变量
    数组与内存控制2--数组使用
    数组与内存控制1--数组初始化
    Java 三大特征之--多态
    简述Java面向对象三大特征:封装、继承、多态
    java程序初始化的顺序
    关于public static void main(String[] args)相关知识
    Java的优点
    前端面试攻略3------HTML和CSS部分
    前端面试攻略2------计算机网络部分
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7448710.html
Copyright © 2020-2023  润新知