样例输入
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
样例输出
样例解释
农场2到农场6有20+3+13=36的距离
析:LCA模板先将 x与y翻到同一深度,然后继续上翻,利用二进制
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define re register int
#define N 500100
using namespace std;
ll sum[N],fa[N][30],p[N][30];
ll to[N<<1],next[N<<1],head[N<<1],w[N<<1];
ll deep[N],dis[N];
ll n,m,k,tot;
ll a,b,c;
char ch[5];
void add(ll x,ll y,ll z)
{
to[++tot]=y;
next[tot]=head[x];
head[x]=tot;
w[tot]=z;
}
void bfs(ll x,ll f)
{
for(re i=1;(1<<i)<=n;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(re i=head[x];i;i=next[i])
{
ll p=to[i];
if(p==f)
continue;
deep[p]=deep[x]+1;
dis[p]=dis[x]+w[i];
fa[p][0]=x;
bfs(p,x);
}
}
ll lca(ll x,ll y)
{
if(deep[x]<deep[y])
return lca(y,x);
ll d=deep[x]-deep[y];
for(re i=0;(1<<i)<=d;i++)
if((1<<i)&d)
x=fa[x][i];
if(x==y)
return x;
for(re i=18;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
int main()
{
scanf("%lld%lld",&n,&m);
for(re i=1;i<=m;i++)
{
scanf("%lld%lld%lld%s",&a,&b,&c,ch);
add(a,b,c);
add(b,a,c);
}
bfs(1,0);
scanf("%lld",&k);
while(k--)
{
scanf("%lld%lld",&a,&b);
//cout<<"dis[a]="<<dis[a]<<" dis[b]="<<dis[b]<<" dis[lca]="<<dis[lca(a,b)]<<" lca="<<lca(a,b)<<endl;
printf("%lld\n",dis[a]+dis[b]-2*dis[lca(a,b)]);
}
return 0;
}