题目来源:
http://codevs.cn/problem/1036/
题目描述:
题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入描述 Input Description
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=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;
}