• 倍增LCA BZOJ1776 cowpol奶牛政坛


    1776: [Usaco2010 Hol]cowpol 奶牛政坛

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 491  Solved: 240
    [Submit][Status][Discuss]

    Description

    农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N。恰好有N-1条单位长度的双向道路,用各种各样的方法连接这些草地。而且从每片草地出发都可以抵达其他所有草地。也就是说,这些草地和道路构成了一种叫做树的图。输入包含一个详细的草地的集合,详细说明了每个草地的父节点P_i (0 <= P_i <= N)。根节点的P_i == 0, 表示它没有父节点。因为奶牛建立了1到K一共K (1 <= K <= N/2)个政党。每只奶牛都要加入某一个政党,其中, 第i只奶牛属于第A_i (1 <= A_i <= K)个政党。而且每个政党至少有两只奶牛。 这些政党互相吵闹争。每个政党都想知道自己的“范围”有多大。其中,定义一个政党的范围是这个政党离得最远的两只奶牛(沿着双向道路行走)的距离。 比如说,记为政党1包含奶牛1,3和6,政党2包含奶牛2,4和5。这些草地的连接方式如下图所 示(政党1由-n-表示):  政党1最大的两只奶牛的距离是3(也就是奶牛3和奶牛6的距离)。政党2最大的两只奶牛的距离是2(也就是奶牛2和4,4和5,还有5和2之间的距离)。 帮助奶牛们求出每个政党的范围。

    Input

    * 第一行: 两个由空格隔开的整数: N 和 K * 第2到第N+1行: 第i+1行包含两个由空格隔开的整数: A_i和P_i

    Output

    * 第1到第K行: 第i行包含一个单独的整数,表示第i个政党的范围。

    Sample Input

    6 2
    1 3
    2 1
    1 0
    2 1
    2 1
    1 5

    Sample Output

    3
    2

    HINT

     

    Source

     
     
    这个题其实比较简单,然而我还是不会......我菜得抠脚
    需要知道这样的一个事情,路径最长的两端点其中必定有一点是该党派中deep[i]最深的那个点,这个应该是显然......
    然而我刚看题的时候天真地认为两段点应该是deep[i]最深的两个点......
    当然这个题可以用一个n*n的暴力枚举,不过显然是要TLE。
    突然觉得vector真是好用,此题中会非常方便地查找一党派中deep[i]最大的那个点
    我废话真多,多半是我太渣,唉......
    这个题,用手写的read竟然比scanf慢,震惊!
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 int n,k,root,ans,mxdeep,mx;
     8 int father[200010],group[200010],deep[200010],fa[200010][32];
     9 vector<int>child[200010],party[200010];
    10 void dfs(int u){
    11     fa[u][0]=father[u];
    12     deep[u]=deep[father[u]]+1;
    13     for(int i=1;(1<<i)<=n;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    14     for(int i=0;i<child[u].size();i++) dfs(child[u][i]);
    15 }
    16 int lca(int u,int v){
    17     if(deep[u]<deep[v]) swap(u,v);
    18     int i=0;
    19     for(i=0;(1<<i)<=n;i++);
    20     i--;
    21     for(int j=i;j>=0;j--)
    22         if(deep[u]-(1<<j)>=deep[v]) u=fa[u][j];
    23     if(u==v) return u;
    24     for(int j=i;j>=0;j--)
    25         if(fa[u][j]!=fa[v][j]){
    26             u=fa[u][j];
    27             v=fa[v][j];
    28         }
    29     return father[u];
    30 }
    31 int main(){
    32     scanf("%d%d",&n,&k);
    33     for(int i=1;i<=n;i++){
    34         scanf("%d%d",&group[i],&father[i]);
    35         child[father[i]].push_back(i);
    36         party[group[i]].push_back(i);
    37         if(!father[i]) root=i;
    38     }
    39     dfs(root);
    40     for(int i=1;i<=k;i++){
    41         ans=0;
    42         mxdeep=0;
    43         mx=0;
    44         for(int j=0;j<party[i].size();j++)
    45             if(deep[party[i][j]]>mxdeep){
    46                 mxdeep=deep[party[i][j]];
    47                 mx=party[i][j];
    48             }
    49         for(int j=0;j<party[i].size();j++)
    50             ans=max(ans,deep[mx]+deep[party[i][j]]-2*deep[lca(mx,party[i][j])]);
    51         printf("%d
    ",ans);        
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    对网页进行抓取时,经常需要判断网页是否可以正常访问,这里我们就可以使用 getcode() 函数获取网页状态码,返回 200 说明网页正常,返回 404 说明网页不存在:
    cvtColor()
    threshold()
    MongoDB 使用数据库对象来创建集合
    定义一个损失函数和优化器 让我们使用分类交叉熵CrossEntropy 作损失函数,动量SGD做优化器。
    2022年8月有感而发
    2022年7月30日
    2022年8月11日
    2022年8月7日
    2022年8月8日
  • 原文地址:https://www.cnblogs.com/zwube/p/6935583.html
Copyright © 2020-2023  润新知