返回顶部

倍增LCA,ST表,DFS序

DFS序

一般与线段树等综合运用,就是将树转换为线段,存在线段树中

点击查看代码
void dfs(int now)
{
	vis[now]=1;
	a[++dfscnt]=x/shuzu[x];//用途线段树 if(l==r)st[rt].val=a[l] 
	in[x]=dfscnt;
	for(int i=head[now];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(!vis[to])
		{
			dfs(to);
		}
	}
	out[now]=dfscnt;
}

ST表

\(i到i+2_{j-1}-1和i+2_{j-1}到i+2_j-1\)
注意j层循环在最外面,i层在里面
因为更新时i+(1<<(j-1))会有后效性

点击查看代码
void st()
{
	for(int i=1;i<=len;i++)
	{
		f[i][0]=a[i];
	}
	for(int j=1;(1<<j)<=len;j++)
	{
		for(int i=1;i+(1<<j)-1<=len;i++)//i+(1<<j)-1表示从i开始(1<<j)-1个长度 
		{
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
}
int query(int l,int r)
{
	int k=0;
	while((1<<(k+1))<=r-l+1)k++;
	return min(f[l][k],f[r-(1<<k)+1][k]);
}

LCA

点击查看代码
int lca(int x,int y)
{
	if(d[x]<d[y])swap(x,y);
	for(int i=31;i>=0;i--)
	{
		if(d[f[x][i]]>=d[y])x=f[x][i];
	}
	if(x==y)return x;
//	for(int i=0;i<=31;i++)
	for(int i=31;i>=0;i--)
	{
		if(f[x][i]!=f[y][i])
		{
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
DFS_init
点击查看代码
void dfs(int x,int fa)
{
	d[x]=d[fa]+1;
	f[x][0]=fa;
	for(int i=head[x];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(to==fa)continue;
		dis[to]=dis[x]+edge[i].w;
		dfs(to,x);
	}	
	
}
void dfs_init()//在DFS之后记得调用这个函数,血的教训
{
	for(int j=1;j<30;j++)
	{
		for(int i=1;i<=n;i++)
		{
			f[i][j]=f[f[i][j-1]][j-1];
			//dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
		}
	}
}
BFS_init
点击查看代码
void bfs()
{
	q.push(1);vis[1]=1;d[1]=1;
	while(q.size())
	{
		int u=q.front();q.pop();
		for(int i=head[u];i;i=edge[i].next)
		{
			int to=edge[i].to;
			if(!vis[to])
			{
				q.push(to);vis[to]=1;
				d[to]=d[u]+1;
				f[to][0]=u;
				for(int j=1;j<30;j++)f[to][j]=f[f[to][j-1]][j-1];
			}
		}
	}
}
posted @ 2024-03-30 20:50  wlesq  阅读(2)  评论(0编辑  收藏  举报