题目大意:求一棵树任意两点的距离
解题报告,设一个数组 dis[i]表示i节点到跟节点的距离,则任意两点的最短距离:dis[i,j]=dis[i]+dis[j]-2*dis[LCA(i,j)]
这个公式还是比较直接的吧
这样就转化成了一个LCA问题。召唤模板
就不吐槽WA到死的代码,换个节点存储方式就过了,简化的数据存储方式可以降低编程复杂度。
PS:此题中的东西南北的方向是不需要的
个人感觉就是1985加上个RMQ模板
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 51000
using namespace std;
vector<int> g[maxn]; //树的存储结构
vector<int> elen[maxn]; //存储边权
int r[maxn]; //RMQ问题中标记节点第一次在e数组中出现的位置
int e[maxn*2]; //RMQ问题中深搜记录边访问的节点
int l[maxn*2]; //RMQ问题中记录节点的访问深度
int dp[maxn*2][20];
int res[maxn*2][20];
int ei,n,m,root,x,y;
bool vis[maxn];
int dis[maxn]; //dis[i]表示i节点到根节点的距离,此题中根节点是1
void init()
{
int x,y,l;
char dir[10];
scanf("%d%d",&n,&m);
memset(dis,0,sizeof(dis));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%s",&x,&y,&l,dir);
g[x].push_back(y);
elen[x].push_back(l);
g[y].push_back(x);
elen[y].push_back(l);
}
}
void _dfs(int u) //深搜确定节点之间的继承关系以及以u为根节点的子树的最远叶子距离
{
vis[u]=1;
int v,vlen=g[u].size();
for(int i=0;i<vlen;i++)
{
v=g[u][i];
if(!vis[v])
{
dis[v]=dis[u]+elen[u][i];
_dfs(v);
}
}
}
void rdfs(int u,int dep)
{
vis[u]=1;
e[ei]=u;
l[ei]=dep;
r[u]=ei;
ei++;
int v,vlen=g[u].size();
for(int i=0; i<vlen; i++)
{
v=g[u][i];
if(!vis[v])
{
rdfs(v,dep+1);
e[ei]=u;
l[ei]=dep;
ei++;
}
}
}
void RMQ_init()
{
for(int i=0; i<ei; i++)
{
dp[i][0]=l[i];
res[i][0]=e[i];
}
for(int j=1; (1<<j)-1<ei; j++)
{
for(int i=0; i+(1<<j)<ei; i++)
{
x=dp[i][j-1];
y=dp[i+(1<<(j-1))][j-1];
if(x<y)
{
dp[i][j]=x;
res[i][j]=res[i][j-1];
}
else
{
dp[i][j]=y;
res[i][j]=res[i+(1<<(j-1))][j-1];
}
}
}
}
int RMQ(int lx,int ly)
{
int len=0;
while(lx+(1<<(len+1))-1<=ly)len++;
x=dp[lx][len];
y=dp[ly-(1<<len)+1][len];
if(x<y)return res[lx][len];
else return res[ly-(1<<len)+1][len];
}
void solve()
{
memset(vis,0,sizeof(vis));
_dfs(1);
memset(vis,0,sizeof(vis));
ei=0;
rdfs(1,1);
RMQ_init();
int a,b;
int ic,ans,x,px;
scanf("%d",&ic);
for(int i=0;i<ic;i++)
{
scanf("%d%d",&a,&b);
if(r[a]>r[b])swap(a,b);
int tar=RMQ(r[a],r[b]);
ans=dis[a]+dis[b]-2*dis[tar];
printf("%d\n",ans);
}
}
int main()
{
freopen("1986.txt","r",stdin);
init();
solve();
return 0;
}