传送门

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. Linux 格式化扩展分区(Extended)

    如果你在Linux系统中格式化磁盘时遇到如下错误,那么表示你正在格式化一个扩展分区. [root@GETTestLNX06 ~]# mkfs.ext4 /dev/sdb1   mke2fs 1.41. ...

  2. MySQL frm+ibd文件还原data的办法【数据恢复】

    MySQL frm+ibd文件还原data的办法[数据恢复] 此方法只适合innodb_file_per_table          = 1 当误删除ibdata 该怎么办? 如下步骤即可恢复: 1 ...

  3. [嵌入式开发]Linux性能分析——上下文切换

    一.从一个问题说起 相信很多人在玩手机还是PC时,都曾碰到过这样一种情况,安装的软件多了系统性能就变慢了,但是去查看CPU利用率一直都低于10%,内存也很充足.我在近期的开发工作中就碰到了类似的情况, ...

  4. Ubuntu下的生活--安装

    概要 整个安装过程是通过离线包安装,而非在线安装. 目录 JDK安装与配置 Eclipse安装与配置 Apache安装与配置 MySQL的安装 JDK安装与配置 版本:jdk-7u71-linux-i ...

  5. java HashMap

    HashMap 的性能因子 1. 容量:表示桶位的数量. 2. 初始容量: 表在创建是所拥有的桶位数.   如果你知道将要在HashMap存储多少项,创建一个初始容量合适的HashMap将可以避免自动 ...

  6. Redis学习和环境搭建

    基本的redis教程,搭建,可以参照下面任一教程: 地址一:http://www.yiibai.com/redis/redis_quick_guide.html 地址二:http://www.runo ...

  7. strcat 函数的实现

    原型        extern char *strcat(char *dest,char *src); 用法        #include <string.h> 功能        把 ...

  8. Selenium2(WebDriver)_如何判断WebElement元素对象是否存在

    1. selenium中如果去寻找元素,而元素不存在的话,通常会抛出NoSuchElementException 导致测试失败,但有时候,我们需要去确保页面元素不存在,才是我们正确的验收条件下面的方法 ...

  9. Linux Kernel代码艺术——系统调用宏定义

    我们习惯在SI(Source Insight)中阅读Linux内核,SI会建立符号表数据库,能非常方便地跳转到变量.宏.函数等的定义处.但在处理系统调用的函数时,却会遇到一些麻烦:我们知道系统调用函数 ...

  10. EhCache的配置

    JPA和Hibernate的二级缓存都是这样做的 代码目录: 这是基础的jar包,如果少的话,再去maven下载 <!-- Spring --> <dependency> &l ...