倍增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

Gold

这个题其实比较简单,然而我还是不会......我菜得扣脚

需要知道这样的一个事情,路径最长的两端点其中必定有一点是该党派中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\n",ans);
52     }
53     return 0;
54 }
时间: 2024-08-01 00:40:19

倍增LCA BZOJ1776 cowpol奶牛政坛的相关文章

bzoj1776[Usaco2010 Hol]cowpol 奶牛政坛*

bzoj1776[Usaco2010 Hol]cowpol 奶牛政坛 题意: 给出一个树,每个节点k个政党中的一个.问每个政党间最远的两个节点距离多少.节点数≤200000. 题解: 有个结论:每个政党所求两个节点其中一个必然是这个政党中深度最大的节点.因此枚举每个节点,计算该节点与节点所属政党深度最大节点的距离(倍增法),与给政党的答案比较即可. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorit

【LCA】BZOJ1776-[Usaco2010 Hol]cowpol 奶牛政坛

[题目大意] 一棵n个点的树,树上每个点属于一个党派,要求每个党派的最远距离点.两点间距离为两点间边的个数. [思路] yy一下可知,最远距离点中必有一个是该党派深度最深的一个,那么我们就记下最深的点,然后枚举跑LCA--O(nlongn)裸的倍增LCA. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=200000+50; 4 const int DEG=20; 5 int n,k,rt; 6 int dep

COGS——T 803. [USACO Hol10] 政党 || 1776: [Usaco2010 Hol]cowpol 奶牛政坛

http://www.lydsy.com/JudgeOnline/problem.php?id=1776||http://cogs.pro/cogs/problem/problem.php?pid=803 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 507  Solved: 246[Submit][Status][Discuss] Description 农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N.

bzoj [Usaco2010 Hol]cowpol 奶牛政坛【树链剖分】

意识流虚树 首先考虑只有一个党派,那么可以O(n)求树的直径,步骤是随便指定一个根然后找距离根最远点,然后再找距离这个最远点最远的点,那么最远点和距离这个最远点最远的点之间的距离就是直径 那么考虑多党派,也这样做,假如有一棵只有这个党派的牛构成的虚树,那么求直径也可以按照上面的做法 但是实际上并不用虚树,直接在这个党派的牛中1.随便选一个牛然后找到距离它最远的本党派牛w 2.找到距离牛w最远的本党派牛,这之间的距离就是答案 求树上距离用deep相减(树剖求lca #include<iostrea

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些

【bzoj4242】水壶 BFS+最小生成树+倍增LCA

题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外. JOI君因为各种各样的事情,必须在各个建筑物之间往返.虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水.此外,原野上没有诸如自动售货机.饮水处之类的东西,因此IOI市的市民一般都携带水壶出

Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]

题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_dis[i],维护非子树节点中距离该点的最大值fa_dis[i]; 2.对于每个节点维护它最大的三个儿子节点的son_dis; 3.维护up[i][j]和down[i][j]数组,这个类似倍增lca里边的fa[i][j],up[i][j]代表的含义是从第j个点向上到它的第2^i个父节点这条链上的点除了该

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写