您的位置:首页 > 产品设计 > UI/UE

POJ1986 Distance Queries(树链剖分LCA)

2016-03-05 17:08 337 查看
个人认为是树链剖分求lca的基本题目,当然其他方法也可以做。

大意:给出一棵n个节点的树,k(1<=k<=10000)个询问,每次询问树上两点的距离(每条道路后面输入的那个字母根本没什么卵用)

首先预处理每个节点i到根节点的距离,然后dis(i,j)=dis(i,root)+dis(j,root)−2∗dis(lca(i,j),root)dis(i,j)=dis(i,root)+dis(j,root)-2*dis(lca(i,j),root),时间复杂度为O(logn)O(logn)

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 40010
using namespace std;
struct tr
{
int v,w,next;
}edge[MAXN*2];
int head[MAXN],cnt;
void add_edge(int u,int v,int w)
{
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
int n,m,q,x,y,z;
int htp[MAXN],son[MAXN],sz[MAXN],dis[MAXN],fa[MAXN],dep[MAXN];
char ops[3];
void dfs1(int u,int f)
{
int maxnv = 0;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(v == f) continue;
dep[v] = dep[u]+1;
dis[v] = dis[u]+edge[i].w;
fa[v] = u;
dfs1(v,u);
sz[u] += sz[v];
if(sz[v] > sz[maxnv]) maxnv = v;
}
sz[u]++;
son[u] = maxnv;
}
void dfs2(int u,int tp)
{
htp[u] = tp;
if(son[u] == 0) return;
dfs2(son[u],tp);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(v == fa[u]||v == son[u]) continue;
dfs2(v,v);
}
}
int LCA(int u,int v)
{
while(1)
{
if(htp[u] == htp[v])
return dep[u]<=dep[v]?u:v;
else if(dep[htp[u]] >= dep[htp[v]])
u = fa[htp[u]];
else v = fa[htp[v]];
}
}
int Dis(int u,int v)
{
return dis[u]+dis[v]-2*dis[LCA(u,v)];
}
int main()
{
memset(head,-1,sizeof head);
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d%s",&x,&y,&z,ops);
add_edge(x,y,z);
add_edge(y,x,z);
}
scanf("%d",&q);
dfs1(1,-1);
dfs2(1,1);
for(int i = 1; i <= q; i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",Dis(x,y));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: