Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

hdu 2856 (LCA)

$
0
0

最近公共祖先问题,,,今天学了LCA离线,,就做了这道题,dis[i]+dis[j]-2*dis[LCA(i,j)],dis是所有点到根节点的距离,,

LCA:从根节点开始形成一颗深搜树,刚开始每个节点属于一个集合,当回溯到节点u时,u的子树都已经遍历,把u的所有子树节点都加入到u这个集合中形成一个集合,然后处理关于u的查询,若查询(u,v)v已经遍历过,LCA(u,v)=(v所在集合的祖先)。







#include<stdio.h>
#include<string.h>
#define N 40001
int vis[N],dis[N],num,head[N],first[N],nume,n,m,f[N];
struct edge
{
	int st,ed,next,w;
}E[N*2];
struct point
{
	int x,y,next,node;
}p[410];
void addedge(int x,int y,int w)
{
	E[num].st=x;
	E[num].ed=y;
	E[num].w=w;
	E[num].next=head[x];
	head[x]=num++;
}
void addpoint(int x,int y)
{
	p[nume].x=x;
	p[nume].y=y;
	p[nume].node=-1;
	p[nume].next=first[x];
	first[x]=nume++;
}
int find(int a)
{
	if(f[a]!=a)
		f[a]=find(f[a]);
	return f[a];
}
void Tarjan(int u)
{
	int i,v;
	vis[u]=1;//已经遍历
	f[u]=u;	//自己形成一个集合
	for(i=head[u];i!=-1;i=E[i].next)
	{
		v=E[i].ed;
		if(vis[v]==1)continue;
		dis[v]=dis[u]+E[i].w;//到根节点的距离
		Tarjan(v);
		f[v]=u;//把子树合并到父节点
	}
	for(i=first[u];i!=-1;i=p[i].next)
	{
		int v=p[i].y;
		if(vis[v]==1)//如果v已经遍历
			p[i/2*2].node=find(v);//找v所在集合的祖先
		    //因为加的是向边,所以把结果都存在第一条边上
	}
}
int main()
{
	int i,m,t,x,y,w;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		memset(head,-1,sizeof(head));
		num=0;
		for(i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&w);
			addedge(x,y,w);
			addedge(y,x,w);
		}
		memset(first,-1,sizeof(first));
		nume=0;
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			addpoint(x,y);//要加双向边,如果先遍历到x,y没遍历就没有结果,
			addpoint(y,x);
		}
		dis[1]=0;
		memset(vis,0,sizeof(vis));
		Tarjan(1);
		for(i=0;i<nume;i+=2)
			printf("%d\n",dis[p[i].x]+dis[p[i].y]-2*dis[p[i].node]);
	}
	return 0;
}
		


建树,直接求:



#include<stdio.h>
#include<string.h>
#define N 40001
int head[N],num,n,dfs[N],father[N],vis[N],dis[N];
struct edge
{
	int st,ed,next,w;
}E[N*2];
void addedge(int x,int y,int w)
{
	E[num].st=x;
	E[num].ed=y;
	E[num].w=w;
	E[num].next=head[x];
	head[x]=num++;
}
void dfs1(int u)
{
	int i,v;
	vis[u]=1;
	for(i=head[u];i!=-1;i=E[i].next)
	{
		v=E[i].ed;
		if(vis[v]==1)continue;
		dfs[v]=dfs[u]+1;
		father[v]=u;
		dis[v]=E[i].w;
		dfs1(v);
	}
}
int LCA(int x,int y)
{
	int sum=0;
	while(dfs[x]>dfs[y])
	{
		sum+=dis[x];
		x=father[x];
	}
	while(dfs[y]>dfs[x])
	{
		sum+=dis[y];
		y=father[y];
	}
	while(x!=y)
	{
		sum+=(dis[x]+dis[y]);
		x=father[x];
		y=father[y];
	}
	return sum;
}
int main()
{
	int i,k,t,x,y,w;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		memset(head,-1,sizeof(head));
		num=0;
		for(i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&w);
			addedge(x,y,w);
			addedge(y,x,w);
		}
		memset(vis,0,sizeof(vis));
		dis[1]=0;
		dfs[1]=0;
		father[1]=0;
		dfs1(1);
		while(k--)
		{
			scanf("%d%d",&x,&y);
			printf("%d\n",LCA(x,y));
		}
	}
	return 0;
}






作者:aixiaoling1314 发表于2013-8-2 16:55:27 原文链接
阅读:31 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles