牛客暑假训练4 A. LCT

原题链接:A-LCT

题意:给一颗有根树,依次给出n-1行的信息,分别为a,b,c,意思是链接a和b之后,询问以c为根节点的最大深度。保证询问c的时候,c不会是其他节点的儿子。

思路:先构建出树,然后从根节点跑出每个节点的深度。因为题目保证了询问c的时候,c不会是其他节点的儿子,所以顺序的求出当前联通块的根节点的深度,这个深度就是之后询问这个点的答案。

//冷静,冷静,冷静
//调不出来就重构
#pragma GCC optimize(2)
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pii;
const int N=1e6+10,mod=1000000007;
ll fa[N];
ll a[N],b[N],c[N],ans[N];
vector<ll> mp[N];
ll cnt[N];
ll h[N];
ll find(ll x)
{
	if(x==fa[x])return x;
	return fa[x]=find(fa[x]);
}
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll t;cin>>t;
	while(t--)
	{
		ll n;cin>>n;
		for(int i=1;i<=n;i++)
		{
			mp[i].clear();
			cnt[i]=0,h[i]=0,fa[i]=i,ans[i]=0;
		}
		for(int i=1;i<n;i++)
		{
			cin>>a[i]>>b[i]>>c[i];
			mp[a[i]].push_back(b[i]);
			cnt[b[i]]++;
		}
		ll foot=-1;
		for(int i=1;i<=n;i++)
		{
			if(cnt[i]==0)
			{
				foot=i;
				break;
			}
		}
		queue<ll> op;
		op.push(foot);
		while(op.size())
		{
			ll v=op.front();op.pop();
			for(auto w:mp[v])
			{
				h[w]=h[v]+1;
				op.push(w);
			}
		}
		for(int i=1;i<n;i++)
		{
			ll x=a[i],y=b[i],z=c[i];
			fa[find(y)]=fa[find(x)];//将b合并到a  
			ans[find(x)]=max(ans[find(y)],ans[y]+h[y]-h[find(x)]);
			//如果x是其他点的子节点,那么之后的询问中,x这个节点肯定不会被询问,因为题目保证询问的点肯定不是其他点的子节点,所以只需要更新当前点的祖宗节点就可以了 
			//ans[y]代表y为根节点的深度,h[y]-h[find(x)]代表y节点于x的祖宗节点的距离,相加就是新的答案
			//因为可能存在其他分叉,所以需要和x祖宗节点本身答案进行比较 
			cout<<ans[z]<<' ';
		}
		cout<<endl;
	}
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值