现在的位置: 首页 > 综合 > 正文

POJ–1986[Distance Queries] DFS+RMQ(最近公共祖先)

2013年03月05日 ⁄ 综合 ⁄ 共 1731字 ⁄ 字号 评论关闭
 

题目大意:
给你一棵树,求任意两结点u,v之间的距离。

 

 

 

源代码:

 

/*DFS+RMQ(最近公共祖先)*/
/*
注:
(1):Index[x]:表示标号x的结点最早出现的位置
(2):R[]:按dfs访问顺序存每个结点的标号
(3):depth[x]:表示标号x的结点离root的距离
(4):Id[u]=v:表示输入时的u结点被标号为v
*/
/*AC代码:344ms*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#define MAXN 40005
#define min(a,b) (a<b?a:b)
using namespace std;

struct edge
{
	int u,v,w,next; 
}E[3*MAXN];
int head[MAXN],ecnt;
int N,M,Q,cnt,num;
int Index[MAXN],R[2*MAXN],depth[MAXN],Id[MAXN];
int Min[2*MAXN][30];
bool vis[MAXN];

//-----------------返回区间最大最小值-----------------//
void RMQ_Init()//O(nlogn)
{
	int i,j,m;
	for(i=1;i<=2*N;i++)
		Min[i][0]=R[i];
	m=(int)(log((double)2*N)/log(2.0));
	for(i=1;i<=m;i++)
	{
		for(j=1;j+(1<<i)-1<=2*N;j++)
			Min[j][i]=min(Min[j][i-1],Min[j+(1<<(i-1))][i-1]);
	}
}
int RMQ_min(int l,int r)//O(1)
{
	int m=(int)(log((double)(r-l+1))/log(2.0));
	return min(Min[l][m],Min[r-(1<<m)+1][m]);
}
//----------------------------------------------------//


void Insert(int u,int v,int w)
{
	E[ecnt].u=u;
	E[ecnt].v=v;
	E[ecnt].w=w;
	E[ecnt].next=head[u];
	head[u]=ecnt++;
}
void Init()
{
	int i,u,v,w;
	char ss[5];
	memset(head,-1,sizeof(head));ecnt=0;
	for(i=1;i<=M;i++)
	{
		scanf("%d%d%d%s",&u,&v,&w,ss);
		Insert(u,v,w);
		Insert(v,u,w);
	}
}
void dfs(int u,int dep)
{
	int i,v;
	depth[Id[u]]=dep;
	R[++num]=Id[u];
	Index[Id[u]]=num;//第一次出现的位子
	for(i=head[u];i!=-1;i=E[i].next)
	{
		v=E[i].v;
		if(!vis[v])
		{
			vis[v]=true;
			Id[v]=++cnt;//标号
			dfs(v,dep+E[i].w);
			R[++num]=Id[u];
		}
	}
}
void swap(int &a,int &b)
{
	int t;
	t=a;a=b;b=t;
}
void Solve()
{
	int u,v;
	memset(vis,false,sizeof(vis));
	cnt=num=0;
	Id[1]=++cnt;
	vis[1]=true;
	dfs(1,0);
	RMQ_Init();
	scanf("%d",&Q);
	while(Q--)
	{
		scanf("%d%d",&u,&v);
		if(Index[Id[u]]>Index[Id[v]])
			swap(u,v);
		int x=RMQ_min(Index[Id[u]],Index[Id[v]]);
		printf("%d\n",depth[Id[u]]+depth[Id[v]]-2*depth[x]);
	}
}
int main()
{
	while(scanf("%d%d",&N,&M)!=EOF)
	{
		Init();
		Solve();
	}
	return 0;
}




抱歉!评论已关闭.