传送门

Description

某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。

假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。

你的任务是帮助该商人计算一下他的最短旅行时间。

Input

输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=ab<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。

Output

在输出文件中输出该商人旅行的最短时间。

Sample Input

5
1 2
1 5
3 5
4 5
4
1
3
2
5

Sample Output

7

思路

  很裸的最近公共祖先的题目,跑一遍spfa记录首都到各个城市的距离,然后找到两点的最近公共祖先,这样就可以根据距离以及最近公共祖先算出两点的最短路了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 30005;
int tot = 0,road[maxn],dis[maxn],flag[maxn],vis[maxn],head[maxn],fa[maxn],ancestor[maxn];
struct Edge{
	int to,next;
}edge[maxn<<1];

int tt = 0,h[maxn],answer[maxn];
struct Query{
	int q,next;
	int index;
}qry[maxn<<1];

void init(int N)
{
	for (int i = 0;i <= N;i++)
	{
		fa[i] = i;ancestor[i] = 0;
		vis[i] = false;
		head[i] = h[i] = -1;
	}
}

void addedge(int u,int v)
{
	edge[tot] = (Edge){v,head[u]};
	head[u] = tot++;
}

void add_query(int u,int v,int index)
{
	qry[tt] = (Query){v,h[u],index};
	h[u] = tt++;
	qry[tt] = (Query){u,h[v],index};
	h[v] = tt++;
}

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

int find(int x)
{
	int r = x;
	while (r != fa[r])	r = fa[r];
	int i = x,j;
	while (i != r)
	{
		j = fa[i];
		fa[i] = r;
		i = j;
	}
	return r;
}

void Union(int x,int y)
{
	x = find(x),y = find(y);
	if (x == y)	return;
	fa[y] = x;
}

void targin_LCA(int u)
{
	ancestor[u] = u;
	vis[u] = true;
	for (int i = head[u]; i != -1;i = edge[i].next)
	{
		int v = edge[i].to;
		if (vis[v])	continue;
		targin_LCA(v);
		Union(u,v);
		ancestor[find(u)] = u;
	}
	for (int i = h[u];i != -1;i = qry[i].next)
	{
		int v = qry[i].q;
		if (vis[v])
		{
			answer[qry[i].index] = ancestor[find(v)];
		}
	}

}

int main()
{
	int N,M,u,v,sum = 0;
	scanf("%d",&N);
	init(N);
	for (int i = 1;i < N;i++)
	{
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	spfa();
	scanf("%d",&M);
	scanf("%d",&road[0]);
	for (int i = 1;i < M;i++)	scanf("%d",&road[i]),add_query(road[i-1],road[i],i);
	targin_LCA(1);
	for (int i = 1;i < M;i++)
	{
		sum += dis[road[i]] + dis[road[i-1]] - 2*dis[answer[i]];
	}
	printf("%d\n",sum);
	return 0;
}

  

codevs 1036 商务旅行(Targin求LCA)的更多相关文章

  1. codevs 1036 商务旅行 (倍增LCA)

    /* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...

  2. 倍增法-lca codevs 1036 商务旅行

    codevs 1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意 ...

  3. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  4. codevs——1036 商务旅行

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 某首都城市的商人要经常 ...

  5. 【最近公共祖先】【树链剖分】CODEVS 1036 商务旅行

    树链剖分求lca模板.O(log(n)),就是不倍增嘛~ #include<cstdio> #include<algorithm> using namespace std; # ...

  6. CODEVS 1036 商务旅行

    题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任 ...

  7. 【最近公共祖先】【块状树】CODEVS 1036 商务旅行

    在线块状树LCA模板. #include<cstdio> #include<vector> #include<algorithm> #include<cmat ...

  8. CODEVS——T 1036 商务旅行

    http://codevs.cn/problem/1036/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Descript ...

  9. POJ 1330 Nearest Common Ancestors(Targin求LCA)

    传送门 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26612   Ac ...

随机推荐

  1. transform图形变化

    <!DOCTYPE HTML> <head> <meta charset = "utf-8"> <title>canvas</ ...

  2. [css]我要用css画幅画(七) - 哆啦A梦

    接着之前的[css]我要用css画幅画(六),今天画的有所不同,画的是哆啦A梦,我们小时候对他的称呼其实是小叮当机器猫. (PS:这次我要做的事情,很多人已经做过,这并不是什么创新,我只是在学习并记录 ...

  3. SQL SERVER 2012/2014 链接到 SQL SERVER 2000的各种坑

    本文总结一下SQL SERVER 2012/2014链接到SQL SERVER 2000的各种坑,都是在实际应用中遇到的疑难杂症.可能会有人说怎么还在用SQL SERVER 2000,为什么不升级呢? ...

  4. Linux服务开机自启动设置

    Linux中也有类似于Window中的开机自启动服务,主要是通过chkconfig命令来设置.它主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服 ...

  5. jedis2.4.2连接池配置说明

    大多数情况使用jedis时用的都是默认配置,但有的时候为了调优,提供应用程序的性能,那我们就要知道jedis中参数的意义. JedisPoolConfig config = new JedisPool ...

  6. spf13-vim安装与使用

    一.简介 spf13-vim是Vim插件与配置的一个发行版本,包含了一整套精心挑选的Vim插件,采用Vundle进行插件管理,并且可以通过下列文件进行个性化配置 ~/.vimrc.local #个性化 ...

  7. gpuimage的各种滤镜简介

    #import"GLProgram.h" //Baseclasses #import"GPUImageOpenGLESContext.h" #import&qu ...

  8. 好压(HaoZip)的命令行模式用法介绍

    好压压缩软件,又叫“2345好压”,是一款国产的优秀压缩软件,目前是免费的,据官网介绍,该软件永久免费.官网地址:http://haozip.2345.com/ 本文主要对该软件的命令行模式用法进行介 ...

  9. 电脑控制Android设备的软件——Total Control

    最早开始搞Android开发时,为了调试方便,想找一个Android下的远程控制软件,支持在电脑端远程控制和同步显示Android设备.先后试了360手机助手.Mobizen.Vysor和Mirror ...

  10. STL 堆

    洛谷P3378 [模板]堆 #include <iostream> #include <cstdio> #include <algorithm> #include ...