传送门

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. jQuery对表格的操作及其他应用

    表格操作 1.隔行变色:对普通表格进行隔行换色:单击显示高亮样式:复选框选中高亮 <!DOCTYPE html> <html> <head> <meta ht ...

  2. Linux查看设置系统时区

    关于时区的概念,其实初中地理课已经涉及,很多人都多少了解一些,可能只是细节搞不太清楚.为什么会将地球分为不同时区呢?因为地球总是自西向东自转,东边总比西边先看到太阳,东边的时间也总比西边的早.东边时刻 ...

  3. SQL SERVER Transactional Replication中添加新表如何不初始化整个快照

    在SQL SERVER的复制(Replication)中,有可能出现由于业务需求变更,需要新增一张表或一些表到已有的复制(发布订阅)当中,这种需求应该是很正常,也很常见的.但是在已有的复制(发布订阅) ...

  4. django ORM

    http://www.cnblogs.com/alex3714/articles/5512568.html 常用ORM操作 一.示例Models from django.db import model ...

  5. C++ 栈和堆的区别

    C++中的存储区分为全局数据区.代码区.堆.栈. 全局数据区存放静态数据.全局变量.常量. 代码区存放所有类成员函数和非成员函数的代码. 栈区存放用于函数的返回地址.形参.局部变量.返回类型. 堆区存 ...

  6. iOS 10 的坑:新机首次安装 app,请求网络权限“是否允许使用数据”(转)

    症状 iOS 10 之后,陆陆续续地有用户联系我们,说新机第一次安装.第一次启动的时候,app 首屏一片空白,完全没数据.kill 掉重新打开就好了. 一开始以为是用户网络情况不好,但随着越来越多的用 ...

  7. 有关stm32的问题,程序里面的u8、u16这些是什么意思啊

    u8 是 unsigned charu16 是 unsigned shortu32 是 unsigned int

  8. mysql在linux下的安装

    安装环境:系统是 centos6.5 1.下载 下载地址:http://dev.mysql.com/downloads/mysql/5.6.html#downloads 下载版本:我这里选择的5.6. ...

  9. 2015.2.16 关于delphi web控件打开新网页时弹出关闭页面(js代码)出错的解决办法研究

    参考网址1:http://www.csharpwin.com/csharpspace/2360.shtml...参考网址2:http://www.oschina.net/question/234345 ...

  10. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...