Codevs 1036 商务旅行(LCA 离线) 题解

题目来源:

http://codevs.cn/problem/1036/

题目描述:

 

题目描述 Description

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

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

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

输入描述 Input Description

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

输出描述 Output Description

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

样例输入 Sample Input

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

样例输出 Sample Output

7

数据范围及提示 Data Size & Hint

解题思路:

      裸的lca,就是在处理询问的时候要两两建边,把经过的点按顺序相邻的都当作一次询问,然后把查询的和加起来就是最后的答案了。。。

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <iomanip>
const int maxn=30005;
using namespace std;
struct new1{
	int to,next,val;
}edge[3*maxn];
struct new2{
	int to,next,id;
}query[3*maxn];
int n,m,ans[maxn],dis[maxn],head_e[maxn],head_q[maxn],vis[maxn],father[maxn],cnte,cntq;
void init()
{
	memset(head_e,-1,sizeof(head_e));
	memset(head_q,-1,sizeof(head_q));
	for(int i=1;i<=n;i++)father[i]=i;
}
void addedge(int u,int v,int w)
{
	edge[cnte].val=w;
	edge[cnte].to=v;
	edge[cnte].next=head_e[u];
	head_e[u]=cnte++;
}
void addquery(int u,int v,int id)
{
	query[cntq].id=id;
	query[cntq].to=v;
	query[cntq].next=head_q[u];
	head_q[u]=cntq++;
}
int fi(int x)
{
	if(x==father[x])return x;
	return father[x]=fi(father[x]);
}
void tarjan(int u)
{
	vis[u]=1;
	for(int i=head_e[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!vis[v]){
			dis[v]=dis[u]+edge[i].val;
			tarjan(v);
			father[v]=u;
		}
	}
	for(int i=head_q[u];i!=-1;i=query[i].next){
		int v=query[i].to;
		if(vis[v]){
			int z=fi(v);
			ans[query[i].id]=dis[u]-2*dis[z]+dis[v];
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	init();
	for(int i=1;i<=n-1;i++)
	{
		int a,b;
		cin>>a>>b;
		addedge(a,b,1);
		addedge(b,a,1);
	}
	cin>>m;
	int c,d;
	cin>>c;
	for(int i=1;i<=m-1;i++){
		if(i%2!=0)cin>>d;
		else cin>>c;
		addquery(c,d,i);
		addquery(d,c,i);
	}
	tarjan(1);
	int sum=0;
	for(int i=1;i<=m-1;i++)
	{
		sum+=ans[i];
	}
	cout<<sum<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81198588