题目描述
对二叉树,计算任意两个结点的最短路径长度。
输入
第一行输入测试数据组数 T 第二行输入 n , m 。 n 代表结点的个数, m 代表要查询的数据组数。 接下来 n 行,每行输入两个数,代表1~ n 结点的孩子结点,如果没有孩子结点则输入-1,根节点为1。 接下来 m 行,每行输入两个数,代表要查询的两个结点。
输出
每组测试数据输出 m 行,代表查询的两个结点之间的最短路径长度。
测试样例
输入
1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1
输出
2
4
2
4
#include<bits/stdc++.h>
int t[10005];
using namespace std;
int main(){
int T,n,m;
int a,b;
cin>>T;
while(T--){
memset(t,0,sizeof(t));
cin>>n>>m;// n结点的个数, m查询的数据组数
for(int i=1;i<=n;i++){
cin>>a>>b;
if(a!=-1){
t[a]=i;//a节点的父亲节点是i
}
if(b!=-1){
t[b]=i;
}
}
for(int j=0;j<m;j++){//查询操作 到达公共祖先的步数和
stack<int>s1,s2;
cin>>a>>b;
int tmp1=a,tmp2=b;
while(a!=0){
s1.push(a);
a=t[a];
}
while(b!=0){
s2.push(b);
b=t[b];
}
while(!s1.empty()&&!s2.empty()&&s1.top()==s2.top()){//最近公共祖先
s1.pop();
s2.pop();
}
cout<<s1.size()+s2.size()<<endl;
}
}
}
解法2:转化为图求解最近距离(转载)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4;
const int INF = 1e9;
ll d[maxn+1][maxn+1];//最短路径距离
//初始化函数
void init(int n)
{
for(int i=1;i<=n;++i)//初始化d
{
for(int j=1;j<=n;++j)
d[i][j]=i==j?0:INF;
}
}
//弗洛伊德算法
void floyd(int n)
{
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
if(d[i][k]!=INF&&d[k][j]!=INF&&d[i][j]>d[i][k]+d[k][j])
{
d[i][j]=d[i][k]+d[k][j];
}
}
}
//打印函数
void print(int n)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cout<<d[i][j]<<" ";
cout<<endl;
}
}
//主函数
int main()
{
int T;
int n,m;
int x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
init(n); //初始化
for(int i=1;i<=n;++i) //读入边
{
scanf("%d %d",&x,&y);
if(x!=-1)
d[i][x]=d[x][i]=1;//无向图
if(y!=-1)
d[i][y]=d[y][i]=1;
}
floyd(n);
//print(n);
for(int i=1;i<=m;i++)//读入查询
{
scanf("%d %d",&x,&y);
printf("%d\n",d[x][y]);
}
}
return 0;
}