【LCA】100pts求助
查看原帖
【LCA】100pts求助
481330
sunyizhe还是MC大佬楼主2023/7/16 12:05
//程序算法:最小生成树,LCA
#include <bits/stdc++.h>
using namespace std;
const int N=10010,M=50010,D=log2(N)+2,INF=0x3f3f3f3f;

struct Edge{
	int u,v,w;
	bool operator < (const Edge& rhs) const {
		return w>rhs.w;
	}
}e[M];//e求最大生成树。

vector<Edge> T[N];

//fa并查集求是否在同一个集合,
int n,m,q,log2n,d[N],fa[N],p[N][D],z[N][D];

int find(int x)
{
	if(x!=fa[x])fa[x]=find(fa[x]);
	return fa[x];
}

void kruskal()
{
	//① 初始化
	sort(e+1,e+m+1);
	for(int i=1;i<=n;i++)fa[i]=i;
	
	//② 选边
	for(int i=1;i<=m;i++)
	{
		int x=find(e[i].u),y=find(e[i].v);
		if(x!=y)
		{
			fa[y]=x;
			
			//存图
			T[e[i].u].push_back(e[i]);
			swap(e[i].u,e[i].v);
			T[e[i].u].push_back(e[i]);
		}
	}
}

void dfs(int u)
{
	for(int i=0;i<T[u].size();i++)
	{
		int v=T[u][i].v;
		
		if(!d[v])
		{
			d[v]=d[u]+1;
			p[v][0]=u;
			z[v][0]=T[u][i].w;
			
			for(int j=1;j<=log2n;j++)
			{
				p[v][j]=p[p[v][j-1]][j-1];
				z[v][j]=min(z[v][j-1],z[p[v][j-1]][j-1]);
			}
			
			dfs(v);
		}
	}
}

int LCA(int x,int y)
{
	if(find(x)!=find(y))return -1;//不连通
	
	if(d[x]<d[y])swap(x,y);
	
	int ans=INF;
	for(int j=log2n;j>=0;j--)
		if(d[p[x][j]]>=d[y])
		{
			ans=min(ans,z[x][j]);//x到2^j祖先的最小边
			x=p[x][j];
		}
	
	if(x==y)return ans;
	
	for(int j=log2n;j>=0;j--)
		if(p[x][j]!=p[y][j])
		{
			ans=min(ans,z[x][j]),x=p[x][j];
			ans=min(ans,z[y][j]),y=p[y][j];
		}
	
	return min(ans,min(z[x][0],z[y][0]));
}
int main()
{
	//freopen("input.in","r",stdin);
	//freopen("output.out","w",stdout);
	
	scanf("%d %d",&n,&m);
	log2n=log2(n)+0.5;
	
	memset(z,0x3f,sizeof(z));
	
	for(int i=1;i<=m;i++)
		scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
	
	kruskal();
	
	d[1]=1,dfs(1);
	
	scanf("%d",&q);
	int x,y;
	for(int i=1;i<=q;i++)
	{
		scanf("%d %d",&x,&y);
		printf("%d\n",LCA(x,y));
	}
	
	return 0;
}

目前未找到错误原因,WA 了 Subtask1 的第 11 个点。

2023/7/16 12:05
加载中...