HDU_2586 HowFarAway ( 最近公共祖先LCA | 广度优先搜索BFS )


题目连接

题意

给一张 n 个顶点, n-1 条边的图, 最大二百条询问从 u 到 v 的最近距离

题解

这里是广搜实现的, 起点搜到终点, dis数组保存距离

附上一个大佬的 LCA 三种算法详细讲解


这个题数据太坑了, 这个说好了 n-1 条边, 开这么大的数组存边, 却是一直超时, 把数组开大了就过了. 但这也应该是报 re , 坑

两种存图方式对于这个题来说时间没有影响太多, vector占的内存大了一些

代码

链式前向星存图

在这里插入图片描述

#include <bits/stdc++.h> 
using namespace std; 
#define rg register 
#define sc scanf 
#define pf printf 
typedef long long ll; 

const int MAXN = 4e4+10;
const int MAXM = 9e4+10; // 坑, 链式前向星超时是因为范围开小了, 也不报 re , 太坑了!!
struct EDGE {
	int v, w, to;
}e[MAXM];
int head[MAXM], cnt = 0, dis[MAXN]; bool vis[MAXN];
inline void add ( int u, int v, int w ) {
	e[cnt].v = v, e[cnt].w = w, e[cnt].to = head[u]; head[u] = cnt++;
}

int bfs ( int st, int ed ) {

	queue<int> q;
	while ( !q.empty() ) q.pop();
	memset ( vis, false, sizeof(vis) );
	memset ( dis, 0, sizeof ( dis ) );

	q.push ( st );
	vis[st] = true;

	while ( !q.empty ( ) ) {

		int u = q.front( );
		q.pop( );

		if ( u == ed ) break;

		for ( int k = head[u]; k != -1; k = e[k].to ) {

			int v = e[k].v;
			if ( vis[v] ) continue;

			q.push ( v );
			vis[v] = true;

			dis[v] = dis[u] + e[k].w;
		}
	}
	return dis[ed];
}



int main ( ) {

	int n, m, T, 
		u, v, w;

	sc ( "%d", &T );

	while ( T-- ) {

		sc ( "%d%d", &n, &m );

		cnt = 0, 
		memset( head, -1, sizeof(head) );

		for ( int i = 0; i < n - 1; ++i ) {
			sc ( "%d%d%d", &u, &v, &w );
			add( u, v, w );
			add( v, u, w );
		}

		for ( int i = 0; i < m; ++i ) {
			sc ( "%d %d", &u, &v );
			pf ( "%d\n", bfs( u, v ) );
		}
		if ( T!=0 ) puts( "" );



	}




	return 0;
}

vector模拟邻接表存图

在这里插入图片描述

#include <bits/stdc++.h> 
using namespace std; 
#define rg register 
#define sc scanf 
#define pf printf 
typedef long long ll; 

const int MAXN = 4e4+10;
struct EDGE {
	int v, w;
};
vector<EDGE> e[MAXN];
int dis[MAXN];
bool vis[MAXN];

int bfs ( int st, int ed ) {

	queue<int> q;
	while ( !q.empty() ) q.pop();
	memset ( vis, false, sizeof(vis) );
	memset ( dis, 0, sizeof ( dis ) );

	q.push ( st );
	vis[st] = true;

	while ( !q.empty ( ) ) {

		int u = q.front ();
		q.pop ( );

		if ( u == ed )break;

		for ( int i = 0; i < e[u].size ( ); ++i ) {
			int v = e[u][i].v;
			if ( vis[v] ) continue;
			q.push ( v );
			vis[v] = true;

			dis[v] = dis[u] + e[u][i].w;
		}
	}
	return dis[ed];
}



int main ( ) {

	int n, m, T, 
		u, v, w;

	sc ( "%d", &T );

	while ( T-- ) {

		sc ( "%d%d", &n, &m );

		for ( int i = 0; i <= n; ++i ) 
			e[i].clear ( );

		for ( int i = 0; i < n - 1; ++i ) {
			sc ( "%d%d%d", &u, &v, &w );
			e[u].push_back( (EDGE){ v, w } );
			e[v].push_back( (EDGE){ u, w } );
		}

		for ( int i = 0; i < m; ++i ) {
			sc ( "%d %d", &u, &v );
			pf ( "%d\n", bfs( u, v ) );
		}
		if ( T!=0 ) puts( "" );



	}




	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值