poj 1986 Distance Queries(LCA模板题)
来源:互联网 发布:考勤机采集数据超时 编辑:程序博客网 时间:2024/06/05 04:57
Description
Input
* Line 2+M: A single integer, K. 1 <= K <= 10,000
* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms.
Output
Sample Input
7 61 6 13 E6 3 9 E3 5 7 S4 1 3 N2 4 20 W4 7 2 S31 61 42 6
Sample Output
13336
Hint
Source
分析:首先我们将无根树转为有根树,可以在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)。
贴上代码当模版:
#include <cstdio>
#include <cstring>
#define N 40010
#define M 80010
#define Q 20010
int n,m,q,e,eq;
int first[N],next[M],v[M],w[M];
int first_q[N],next_q[Q],u_q[Q],v_q[Q],lca[Q];
int d[N],p[N];
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 1986 Distance Queries(LCA模板题)
- LCA模板在线 POJ 1986 Distance Queries
- POJ 1986Distance Queries(LCA)
- POJ 1986 Distance Queries [LCA]
- poj 1986 Distance Queries LCA
- POJ 1986 Distance Queries(LCA)
- poj 1986 Distance Queries (LCA)
- POJ 1986 Distance Queries LCA
- [POJ 1986] Distance Queries (LCA)
- Distance Queries - POJ 1986 LCA
- poj 1986 Distance Queries(LCA)
- POJ 1986 Distance Queries【LCA】
- Poj 1986 Distance Queries【LCA】
- POJ 1986 Distance Queries 【LCA】
- |poj 1986|LCA|Distance Queries
- POJ 1986 Distance Queries (Tarjan-LCA算法)(带权值)
- poj 1986 Distance Queries(LCA求两点距离模版)
- POJ 1986 Distance Queries(LCA Tarjan离线算法)
- 桥接多进程OpenVPN虚拟网卡解决多处理问题
- SGU181_X-Sequence(暴力寻找循环节)
- Android编程编码规范
- cvCopy与cvCloneImage的区别
- android管理wifi
- poj 1986 Distance Queries(LCA模板题)
- Android的SDK,NDK以及JNI
- Flex中的Session管理
- jdk1.5新特性
- OpenVPN客户端多处理器的支持
- socket通信之完整的多路复用
- Android之BaseExpandableListAdapter使用心得(QQ续一)
- css总结系列之一
- LeetCode: Integer to Roman