POJ 1986 Distance Queries (离线LCA)
2012-08-03 23:15
375 查看
题意:给一棵带权重的树,共有k个查询,每次查询树中2个结点的距离。结点数n最大为40000,k最大10000
分析:首先我们将无根树转为有根树,可以在O(n)时间内得到每个结点到根结点的距离。由于在树中从一个结点走到另一个结点的路径是唯一的,所以a到b的路径一定经过lca(a,b),设lca(a,b)=c。此时不难发现d(a,b)=d(a,root)+d(b,root)-2*d(c,root)。先在问题就是如何快速求LCA,由于结点数目比较大,查询比较多,所以用在线算法会超时。这里用的是tarjan离线算法,时间复杂度为O(n+k)。
View Code
分析:首先我们将无根树转为有根树,可以在O(n)时间内得到每个结点到根结点的距离。由于在树中从一个结点走到另一个结点的路径是唯一的,所以a到b的路径一定经过lca(a,b),设lca(a,b)=c。此时不难发现d(a,b)=d(a,root)+d(b,root)-2*d(c,root)。先在问题就是如何快速求LCA,由于结点数目比较大,查询比较多,所以用在线算法会超时。这里用的是tarjan离线算法,时间复杂度为O(n+k)。
View Code
#include <stdio.h> #include <string.h> #define N 40010 #define M 80010 #define Q 20010 int n,m,q,e,eq; int first ,next[M],v[M],w[M]; int first_q ,next_q[Q],u_q[Q],v_q[Q],lca[Q]; int d ,p ; bool ok[Q]; void init() { e=eq=0; memset(first,-1,sizeof(first)); memset(first_q,-1,sizeof(first_q)); memset(lca,0,sizeof(lca)); memset(p,-1,sizeof(p)); memset(ok,0,sizeof(ok)); } void add(int a,int b,int c) { v[e]=b; w[e]=c; next[e]=first[a]; first[a]=e++; } void add_q(int a,int b) { u_q[eq]=a; v_q[eq]=b; next_q[eq]=first_q[a]; first_q[a]=eq++; } void make_set(int i) { p[i]=i; } int find_set(int i) { if(i^p[i]) p[i]=find_set(p[i]); return p[i]; } void union_set(int i,int j) { i=find_set(i),j=find_set(j); p[j]=i; } void get_d(int a,int fa) { int i,b; for(i=first[a];i!=-1;i=next[i]) { b=v[i]; if(b^fa) d[b]=d[a]+w[i],get_d(b,a); } } void dfs(int a) { int i,b; make_set(a); for(i=first[a];i!=-1;i=next[i]) { b=v[i]; if(p[b]==-1) { dfs(b); union_set(a,b); } } for(i=first_q[a];i!=-1;i=next_q[i]) if(!ok[i]) { b=v_q[i]; if(p[b]!=-1) lca[i]=find_set(b),ok[i]=true; } } int main() { int a,b,c; char s[3]; while(~scanf("%d%d",&n,&m)) { init(); while(m--) { scanf("%d%d%d%s",&a,&b,&c,s); add(a,b,c); add(b,a,c); } scanf("%d",&q); while(q--) { scanf("%d%d",&a,&b); add_q(a,b); add_q(b,a); } d[1]=0; get_d(1,0); dfs(1); for(int i=0;i<eq;i+=2) { a=u_q[i]; b=v_q[i]; c=lca[i]; if(!c) c=lca[i+1]; printf("%d\n",d[a]+d[b]-2*d[c]); } } return 0; }
相关文章推荐
- poj 1986LCA离线dfs+并查集
- POJ 题目1986 Distance Queries(LCA 离线)
- poj 1986LCA离线dfs+并查集
- POJ - 1986 Distance Queries(LCA离线)
- poj 1986 Distance Queries(LCA:倍增/离线)
- POJ 1986 Distance Queries(LCA在线和离线)
- poj 1986 Distance Queries(LCA离线Tarjan算法)
- 【POJ】 1986 Distance Queries 离线LCA
- POJ 1986 Distance Queries(离线LCA)
- POJ 1986 Distance Queries(离线tarjan-LCA)
- poj 1986 Distance Queries 离线LCA
- poj1986 LCA
- POJ 1986 Distance Queries [LCA]
- 【RMQ+LCA】POJ 1986
- |poj 1986|LCA|Distance Queries
- POJ 1330 Nearest Common Ancestors【LCA_(rmq 在线 + tarjan 离线)】
- POJ - 1470 Closest Common Ancestors(LCA离线)
- POJ 1986 Distance Queries(LCA)
- POJ1470 Closest Common Ancestors(最近公共祖先lca,离线Tarjan)
- POJ 1986 Distance Queries LCA