数据结构作业——sights(最短路/最近公共祖先)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构作业——sights(最短路/最近公共祖先)相关的知识,希望对你有一定的参考价值。

sights

Description

美丽的小风姑娘打算去旅游散心,她走进了一座山,发现这座山有 n 个景点,由于山路难修,所以施工队只修了最少条的路,来保证 n 个景点联通,娇弱的小风姑娘不想走那么长的山路, 所以打算乘坐专用的交通工具。 有的景点之间有路,乘坐交通工具需要花费一定的金额。由于到达景区之前已经花了一部分钱了,现在可爱的小风姑娘站在景点 1,即根景点。按原计划她要去编号为 m 的景点,导游告诉她到景点 m 总共要花的钱(包括来之前花的钱) 。然而善变的小风姑娘突然想去景点 y(直接从景点 1 到景点 y) ,所以她想要知道到景点 y 总共要花多少钱,作为程序员之花,她想用代码来解决这个问题。

Input

输入第一行为一个正整数 n 表示景点的数目,景点从 1 到 n 编号。
接下来 n-1 行,代表山路,每行三个整数 x,y,p,分别表示 x,y 景点间的路费。
第 n+1 行一个整数 q 表示询问组数。每组数据独立互不相关。
紧跟着 q 行,每行三个整数 m,v,y,分别表示 m 景点的编号,到达 m 景点的总花费 v,以及要求的 y 景点。
30%的数据 n<=20,p<=100,q<=10
70%的数据 n<=1000,p<=10000,q<=100
100%的数据 n<=100000,p<=1000000,q<=n

Output

输出 q 行,每行一个整数表示题目要求的答案,由于答案可能很大,输出对
707063423 取余的结果。

Sample Input

4
1 2 5
1 3 6
2 4 4
2
2 8 4
3 6 2

Sample Output

12
5

思路

跑一遍spfa记录下到各个节点的距离。也可以通过最近公共祖先解决问题。

 AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef __int64 LL;
const int maxn = 100010;
const LL mod = 707063423;
const LL INF = 0xffffffff;
struct Edge{
	int u,v,next;
	LL w;
}edge[2*maxn];
int tot = 0,head[maxn];
LL dis[maxn];
bool vis[maxn];

void addedge(int u,int v,LL w)
{
	edge[tot].u = u;edge[tot].v = v;edge[tot].w = w;edge[tot].next = head[u];
	head[u] = tot++;
}

void spfa(int N)
{
	int i;
	memset(vis,false,sizeof(vis));
	for (i = 0;i <= N;i++)	dis[i] = INF;
	queue<int>que;
	while (!que.empty())	que.pop();
	dis[1] = 0;
	que.push(1);
	vis[1] = true;
	while (!que.empty())
	{
		int u = que.front();
		que.pop();
		vis[u] = false;
		for (i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			if (dis[u] + edge[i].w < dis[v])
			{
				dis[v] = dis[u] + edge[i].w;
				if (!vis[v])
				{
					que.push(v);
					vis[v] = true;
				}
			}
		}
	}
}

int main()
{
	//freopen("data.txt","r",stdin);
	//freopen("2.txt","w",stdout);
	int N,u,v,q,m,y,i;
	LL w,cv;
	memset(head,-1,sizeof(head));
	scanf("%d",&N);
	for (i = 0;i < N - 1;i++)
	{
		scanf("%d%d%I64d",&u,&v,&w);
		addedge(u,v,w);
		addedge(v,u,w);
	}
	spfa(N);
	scanf("%d",&q);
	while (q--)
	{
		scanf("%d%I64d%d",&m,&cv,&y);
		cv = (cv - dis[m] + mod)%mod;
		printf("%I64d\n",(dis[y]%mod + cv%mod)%mod);
	}
	return 0;
}

对拍程序

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<time.h>
const int maxn = 100000;
const int maxx = 1000000;

int main()
{
	freopen("data.txt","w",stdout);
	srand(time(NULL));
	int N;
	N = rand();
	printf("%d\n",N);
	for (int i = 2;i <= N;i++)
	{
		int leave = rand()%i;
		while (!leave)
		{
			leave = rand()%i;
		} 
		printf("%d %d %d\n",leave,i,rand()%maxx);
	}
	int M = rand()%maxn;
	printf("%d\n",M);
	while (M--)
	{
		printf("%d %d %d\n",rand()%N + 1,rand(),rand()%N+1);
	}
	return 0;
}

  

 

以上是关于数据结构作业——sights(最短路/最近公共祖先)的主要内容,如果未能解决你的问题,请参考以下文章

最近公共祖先LCA(整理)

最近公共祖先(LCA)---tarjan算法

算法详解之最近公共祖先(LCA)

LCA-tarjan understand

LCA

LeetCode 第 B 题:二叉树任意两节点之间的最短路径