BZOJ 1787: [Ahoi2008]Meet 紧急集合

/*
BZOJ 1787: [Ahoi2008]Meet 紧急集合

LCA

树剖预处理Lca
然后对于要查询的三个点
分别求出三个lca

接下来的事就比较神奇了
手模几组样例后就会发现
三个lca必定会有两个相同

这样的话那个不相同的那个就是所要求的点(自己画画图, 就会非常清楚的明白)
然后分别计算三个点到选出的lca的距离就可以了

*/
#include <cstdio>

#define Max 500097

inline int abs (int a)
{
return a > 0 ? a : -a;
}

inline void swap (int &a, int &b)
{
int now = a;
a = b;
b = now;
}

{
now = 0;
register char word = getchar ();
while (word < '0' || word > '9')
word = getchar ();
while (word >= '0' && word <= '9')
{
now = now * 10 + word - '0';
word = getchar ();
}
}

class Tree_Chain_Lca_Type
{
private :

struct Points
{
int size;
int father;
int up_chain_point;
int deep;
}

point[Max];

int Count;

struct Edges
{
int to;
int next;
}
edge[Max << 2];

int Edge_Count;
int edge_list[Max];

public :

inline void AddEdge (int from, int to)
{
Edge_Count++;
edge[Edge_Count].to = to;
edge[Edge_Count].next = edge_list[from];
edge_list[from] = Edge_Count;
Edge_Count++;
edge[Edge_Count].to = from;
edge[Edge_Count].next = edge_list[to];
edge_list[to] = Edge_Count;
}

void Dfs_1 (int now, int father)
{
int pos = Count++;
point[now].father = father;
point[now].deep = point[father].deep + 1;
for (int i = edge_list[now]; i; i = edge[i].next)
if (edge[i].to != father)
Dfs_1 (edge[i].to, now);
point[now].size = Count - pos;
}

void Dfs_2 (int now, int chain)
{
point[now].up_chain_point = chain;
int pos = 0;
for (int i = edge_list[now]; i; i = edge[i].next)
if (edge[i].to != point[now].father && point[edge[i].to].size > point[pos].size)
pos = edge[i].to;
if (!pos)
return;
Dfs_2 (pos, chain);
for (int i = edge_list[now]; i; i = edge[i].next)
if (edge[i].to != pos && edge[i].to != point[now].father)
Dfs_2 (edge[i].to, edge[i].to);
}

int Get_Lca (int x, int y)
{
while (point[x].up_chain_point != point[y].up_chain_point)
{
if (point[point[x].up_chain_point].deep < point[point[y].up_chain_point].deep)
swap (x, y);
x = point[point[x].up_chain_point].father;
}
return point[x].deep < point[y].deep ? x : y;
}

int Get_dis (int x, int y)
{
int now = Get_Lca (x, y);
return point[x].deep + point[y].deep - (point[now].deep << 1);
}

void Clear ()
{
Dfs_1 (1, 0);
Count = 0;
Dfs_2 (1, 1);
}
};

Tree_Chain_Lca_Type Make;

int N, M;

int main (int argc, char *argv[])
{
int x, y, z;
for (int i = 1; i < N; i++)
{
}
Make.Clear ();
int now_1, now_2, now_3;
while (M--)
{
now_1 = Make.Get_Lca (x, y);
now_2 = Make.Get_Lca (x, z);
now_3 = Make.Get_Lca (y, z);
if (now_1 == now_2)
now = now_3;
else if (now_1 == now_3)
now = now_2;
else
now = now_1;
printf ("%d %d\n", now, Make.Get_dis (x, now) + Make.Get_dis (y, now) + Make.Get_dis (z, now));
}
return 0;
}

myj 吊打我Orz，xxy 捆起来打我Orz，myl 文化课上天Orz， lrh 姿势水平敲高Orz， hkd 特别胖Orz%%%，cys 智商感人Orz，syl zz专业Orz，我没有学上， 我们未来一片光明
posted @ 2017-05-13 20:01  ZlycerQan  阅读(176)  评论(0编辑  收藏  举报