BZOJ3732Network

和洛谷1967一样,只不过是求一个最小生成树,然后和上一道题一样,先构建新图,然后lca求到祖先距离的最大值

代码

//By AcerMo
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=700500;
struct edge
{
	int from,to,cost;
	bool friend operator < (edge a,edge b)
	{
		return a.cost>b.cost;	
	} 
}now;//初始建图 
priority_queue<edge>q;
struct map
{
	int to,cost;
}_233;//新图 
vector<map>v[M];
int n,m,que;
int vis[M/4],deep[M/4],pt[M/4][22];
int fa[M/4],size[M/4],fatt[M/4][22];
int find(int x)
{
	if (x!=fa[x]) return fa[x]=find(fa[x]);
	return x;
}
void unionn(int a,int b)
{
	if (size[a]<=size[b]) size[b]+=size[a],fa[a]=b;
	else size[a]+=size[b],fa[b]=a;
	return ;
}//加入了按秩合并以及路径压缩 
void constt()
{
	for (int i=0;i<=n;i++)
	size[i]=1,fa[i]=i,fatt[i][0]=i,deep[i]=1;
	return ;
}//初始化每个点的信息 
void kru()
{
	int cnt=1;constt();
	while (q.size()&&cnt<n)
	{
		now=q.top();q.pop();
		int r1=find(now.from);
		int r2=find(now.to);
		if (r1!=r2) 
		{
			unionn(r1,r2),cnt++;
			_233.to=now.to;_233.cost=now.cost;v[now.from].push_back(_233);
			_233.to=now.from;_233.cost=now.cost;v[now.to].push_back(_233);
		}//注意加入新图的是原点而不是祖先 
	}
	return ;
}//最大生成树及构建新图 
void getlca(int x)
{
	vis[x]=1;
	for (int i=0;i<v[x].size();i++)
	{
		int go=v[x][i].to;
		if (vis[go]) continue;
		deep[go]=deep[x]+1;
		fatt[go][0]=x;
		pt[go][0]=v[x][i].cost;
		getlca(go);
	}
	return ;
}//构建lca祖先关系 
void getminpath()
{
	for (int i=1;i<=20;i++)
	for (int k=1;k<=n;k++)
	{
		fatt[k][i]=fatt[fatt[k][i-1]][i-1];
		pt[k][i]=max(pt[k][i-1],pt[fatt[k][i-1]][i-1]);
	}
	return ;
}//预处理每个点到祖先的距离 
int lca(int x,int y)
{
	int ans=0;
	if (deep[x]>deep[y]) swap(x,y);
	for (int i=20;i>=0;i--)
		if (deep[fatt[y][i]]>=deep[x]) 
			ans=max(ans,pt[y][i]),y=fatt[y][i];
	if (x==y) return ans;
	for (int i=20;i>=0;i--)
		if (fatt[x][i]!=fatt[y][i])
			ans=max(ans,max(pt[x][i],pt[y][i])),
				x=fatt[x][i],y=fatt[y][i];
	ans=max(ans,max(pt[x][0],pt[y][0]));
	return ans;
}//lca求解 
int main()
{
	scanf("%d%d%d",&n,&m,&que);
	for (int i=1;i<=m;i++)
		scanf("%d%d%d",&now.from,&now.to,&now.cost),q.push(now);
	kru();
	for (int i=1;i<=n;i++)
	if (!vis[i]) getlca(i);
	getminpath();
	while (que--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		int ans=lca(x,y);
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80714082