hdu2586【LCA】【树上距离】【Tarjan】How far away ?

该博客详细介绍了如何使用图论中的深度优先搜索(DFS)算法实现Tarjan算法,结合并查集解决最短路径问题。文章通过实例展示了如何构建图、添加边、查询路径,并利用并查集找到节点的最小公共祖先,进而计算路径长度。博主深入探讨了数据结构和算法在解决实际问题中的应用。
摘要由CSDN通过智能技术生成

here
模板题。

// god with me
//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
//#include <bits/stdc++.h>
//#include <bits/stdc++.h>
#include <cmath>
#include <math.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
//#define double long long
#define re int
//#define i int i
//#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define mk make_pair
#define P pair < int , int >
// typedef long long s64;
using namespace std;
const int mod=1e6+7;
const int N=5e4+5;//?????????? 4e8
const int M=1e5+10;
int ver[M],next1[M],edge[M],head[N];
int fa[N],d[N],v[N],lca[N],ans[N];
vector<int> query[N],query_id[N];
bool vis[N];
int T,n,m,tot,t;

void add1(int x,int y,int z)
{
	ver[++tot]=y;edge[tot]=z;next1[tot]=head[x];head[x]=tot;
}

void add_query(int x,int y,int id)
{
	query[x].pb(y),query_id[x].pb(id);
	query[y].pb(x),query_id[y].pb(id);
}
int get(int x) 
{
	if(x==fa[x]) return x;
	return fa[x]=get(fa[x]);
}

void tarjan(int x)
{
	v[x]=1;
	for(int i=head[x];i;i=next1[i])
	{
		int y=ver[i];
		if(v[y])  continue;
		d[y]=d[x]+edge[i];
		tarjan(y);
		fa[y]=x;
	}	
	for(int i=0;i<query[x].size();i++)
	{
		int y=query[x][i],id=query_id[x][i];
		if(v[y]==2)
		{
			int lca=get(y);
			
//			ans[id]=get(y);
			ans[id]=min(ans[id],d[x]+d[y]-2*d[lca]);
		}
	}
	v[x]=2;
}

void solve()
{
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{
		vis[i]=false;
		d[i]=inf;
		head[i]=v[i]=0;fa[i]=i;
		query[i].clear(),query_id[i].clear();
	}
	tot=0;
	for(int i=1;i<n;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		add1(x,y,z);
		add1(y,x,z);
		vis[y]=1;
	}
//	cin>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		if(x==y)  ans[i]=0;
		else
		{
			add_query(x,y,i);
//			add_query(y,x,i);
			ans[i]=1<<30;
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
		{
//			cout<<i<<endl;
			d[i]=0;
			tarjan(i);
			break; 
		}
	}
//	tarjan(1);
	for(int i=1;i<=m;i++)  cout<<ans[i]<<endl;
}


signed main()
{
//	ios::sync_with_stdio(false);
    int T=1;
    cin>>T;
    for(int index=1;index<=T;index++)
    {
//      printf("Case %d:\n",index);
        solve();
//        puts("");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

while WA er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值