题目大意:
其实就是给你一颗三叉树,让你求树上任意两点之间的最近距离
解题思路:
求各个点到树的根的距离,然后计算要查询的这些点的最近共组先。
如图所示,求4与2之间的距离的办法就是dis[4]+dis[2]-2dis[3];而3其实就是2与4的最近公共祖先了。
最近公共最先的求法————Tarjan算法:(自己百度吧。。。)
代码:
#include<stdio.h>
#define N 10000*8+10
struct node{
int to,dis,next;
};
node edg[N];
int head[N],h;
void aeg(int a,int b,int d)
{
edg[h].to=b;
edg[h].dis=d;
edg[h].next=head[a];
head[a]=h++;
}
struct qnode{
int lca;
int to;
int next;
};
int qhead[N];
qnode qedg[N];
void aqeg(int a,int b)
{
qedg[h].to=b;
qedg[h].next=qhead[a];
qhead[a]=h++;
}
int p[N];
int findp(int x)
{
int k,y=x;
while(x!=p[x])x=p[x];
// while(y!=p[y]){
// k=y;y=p[y];p[k]=x;不能合并
// }
return x;
}
bool visit[N];
int dis[N];
void LCA(int u,int w)
{
p[u]=u;
dis[u]=w;
visit[u]=true;
int i,v;
for(i=head[u];i!=-1;i=edg[i].next)
{
v=edg[i].to;
if(!visit[v])
{
LCA(v,dis[u]+edg[i].dis);
p[v]=u;
}
}
for(i=qhead[u];i!=-1;i=qedg[i].next)
{
v=qedg[i].to;
if(visit[v])
{
qedg[i].lca=findp(v);
qedg[i^1].lca=qedg[i].lca;
}
}
}
void init(int n)
{
int i;
for(i=0;i<n+10;i++)
{
p[i]=i;
dis[i]=0;
}
for(i=0;i<N;i++)
head[i]=qhead[i]=-1;
}
int main()
{
int u,v,d,n,m,i;
char buf[10];
while(scanf("%d%d",&n,&m)!=EOF)
{
init(n);
h=0;
while(m--)
{
scanf("%d%d%d%s",&u,&v,&d,buf);
aeg(u,v,d);
aeg(v,u,d);
}
scanf("%d",&m);
h=0;
n=m;
while(m--)
{
scanf("%d%d",&u,&v);
aqeg(u,v);
aqeg(v,u);
}
LCA(1,0);
// for(i=1;i<=n;i++)
// printf("%d ",dis[i]);
int lca;
for(i=0;i<n*2;i++){
u=qedg[i].to;v=qedg[i+1].to;lca=qedg[i].lca;
i++;
// printf("%d %d %d\n",u,v,lca);
d=dis[u]+dis[v]-2*dis[lca];
printf("%d\n",d);
}
}
}