LCA 离线targin模板

参考文章:https://www.cnblogs.com/jsawz/p/6723221.html

模板题目:POJ1330   有根树 节点1W,查询1次 , 耗时:282ms

//targin 模板 2018.5.8 
#include<stdio.h>
#include<memory.h>
#include<set>
using namespace std;
const int maxn = 10000+10;//一共有多少个节点 
const int maxm = 20000+10;//一共有多少条边
struct Node
{
	int to;
	int next;
	int lca;	
};
Node qedge[4];//要查询的边
Node edge[maxm];//存放顶点的邻接表
int n,m,q;//顶点数,边数 查询数 
int head[maxn],qhead[maxn];//head记录顶点i的第一条边的位置,qhead记录相关查询的第一条边的位置 
int edgeNum,qedgeNum; //树的边数 edgeNum ,查询的数目qedgeNum 
int f[maxn],visit[maxn];//并查集要用到的数组
set<int>s;//找出根节点要用到的集合
void add_edge(int from,int to)
{
	edge[++edgeNum].next = head[from];
	edge[edgeNum].to = to;
	head[from] = edgeNum;
}
void add_qedge(int from,int to)
{
	qedge[++qedgeNum].next = qhead[from];
	qedge[qedgeNum].to = to;
	qhead[from] = qedgeNum;
}
int find(int x) //查询父节点
{
	if(f[x]!=x)
	{
		f[x] = find(f[x]);
	}
	return f[x];
}
void targin(int u)
{
	f[u] = u;
	visit[u] = 1;
	for(int k = head[u] ; k ; k = edge[k].next)//遍历顶点u的邻接表
	{
		if(visit[edge[k].to]==1)
		{
			continue;
		}
		targin(edge[k].to);
		f[edge[k].to] = u;//合并
	}
	for(int k=qhead[u] ; k ; k = qedge[k].next)//找有关顶点u的查询 
	{
		if(visit[qedge[k].to]==1)//另外一个节点已经求出来了
		{
			qedge[k].lca = find(qedge[k].to);
			
			if(k%2==1)
			{
				qedge[k+1].lca = qedge[k].lca;
			}else{
				qedge[k-1].lca = qedge[k].lca;
			}
		}
	}
}
void init() //初始化
{
	s.clear();
	edgeNum = qedgeNum = 0;
	for(int i=1;i<=n;i++)
	{
		visit[i] = 0;
		head[i] = 0;
		qhead[i] = 0;
		s.insert(i);
	}
}
int main()
{
	int t;
	scanf("%d",&t);//测试数
	while(t--)
	{
		scanf("%d",&n);
		init();//初始化 
		m = n -1;  //题目说了,边数m = 顶点数-1
		q = 1;     //题目说了,查询数目 只有1 个
		qedgeNum = edgeNum = 0;
		for(int i=1;i<=m;i++)//输入边数 
		{
			int from,to;
			scanf("%d %d",&from,&to);
			s.erase(to);
			add_edge(from,to);
			add_edge(to,from);
		}
		for(int i=1;i<=q;i++)
		{
			int from,to;
			scanf("%d %d",&from,&to);
			add_qedge(from,to);
			add_qedge(to,from);
		}
		targin(*s.begin());//以该点作为根节点 
		for(int i=1;i<=q;i++) 
		{
			printf("%d\n",qedge[i*2].lca);
		}
	}
	return 0;
}

hdu 2586   无根 ,节点4W,查询200  耗时:46ms

//targin 模板 2018.5.8 
#include<stdio.h>
#include<memory.h>
const int maxn = 40000+10;//一共有多少个节点 
const int maxm = 80000+10;//一共有多少条边
struct Node
{
	int from;
	int to;
	int next;
	int lca;	
	int len; 
};
Node qedge[200*2+10];//要查询的边
Node edge[maxm];//存放树的边
int n,m,q;//顶点数,边数 查询数 
int head[maxn],qhead[maxn];//记录顶点i的第一条边的位置,和相关查询的第一条边的位置 
int edgeNum,qedgeNum; //树的边数 edgeNum ,查询的数目qedgeNum 
int f[maxn],visit[maxn];
int d[maxn];
void add_edge(int from,int to,int len)
{
	edge[++edgeNum].next = head[from];
	edge[edgeNum].to = to;
	edge[edgeNum].len = len;
	head[from] = edgeNum;
}
void add_qedge(int from,int to)
{
	qedge[++qedgeNum].next = qhead[from];
	qedge[qedgeNum].from = from;
	qedge[qedgeNum].to = to;
	qhead[from] = qedgeNum;
}
int find(int x)
{
	if(f[x]!=x)
	{
		f[x] = find(f[x]);
	}
	return f[x];
}
void targin(int u)
{
	f[u] = u;
	visit[u] = 1;
	for(int k = head[u] ; k ; k = edge[k].next)
	{
		if(visit[edge[k].to]==1)
		{
			continue;
		}
		d[edge[k].to] = d[u] + edge[k].len;
		targin(edge[k].to);
		f[edge[k].to] = u;//合并
	}
	for(int k=qhead[u] ; k ; k = qedge[k].next)//找有关顶点u的查询 
	{
		if(visit[qedge[k].to]==1)// 
		{
			qedge[k].lca = find(qedge[k].to);
			
			if(k%2==1)
			{
				qedge[k+1].lca = qedge[k].lca;
			}else{
				qedge[k-1].lca = qedge[k].lca;
			}
		}
	}
}
void init()
{
	edgeNum = qedgeNum = 0;
	for(int i=1;i<=n;i++)
	{
		visit[i] = 0;
		head[i] = 0;
		qhead[i] = 0;
		d[i] = 0;
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&q); //输入节点数,输入边数,输入查询数 
		init();//初始化 
		m = n-1;
		qedgeNum = edgeNum = 0;
		for(int i=1;i<=m;i++)//输入边数 
		{
			int from,to,len;
			scanf("%d %d %d",&from,&to,&len);
			add_edge(from,to,len);
			add_edge(to,from,len);
		}
		for(int i=1;i<=q;i++)
		{
			int from,to;
			scanf("%d %d",&from,&to);
			add_qedge(from,to);
			add_qedge(to,from);
		}
		targin(1);//以1作为根节点 
//		for(int i=1;i<=n;i++)
//		{
//			printf("%d ",visit[i]);
//		}
//		printf("\n");
		for(int i=1;i<=q;i++)
		{
			int from,to,lca;
			from = qedge[i*2].from;
			to = qedge[i*2].to;
			lca = qedge[i*2].lca;
			 
			printf("%d\n",d[from]+d[to]-2*d[lca]);
		}
	}
	return 0;
}




猜你喜欢

转载自blog.csdn.net/zark721/article/details/80247568