思路:在联通块中,将每个点到根节点的距离记录下来,通过这个距离来判断两点的关系;
关于”距离“的解释和举例:
代码实现:
注意:在全文中 sa是代表字符串a ,ra是字符串a的父节点的意思
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
unordered_map<string ,string> p;//p数组存父亲节点
unordered_map<string ,double> d;//d数组存此节点到父亲节点的距离
string gap; //单纯输入的时候吞掉多余的字符串
string findd(string a)//查找父节点和压缩路径的函数
{
if(a!=p[a])
{
string ra=findd(p[a]);
d[a]*=d[p[a]];
p[a]=ra;
}
return p[a];
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)//插入
{
double a,b;
string sa,sb;
cin>>a>>sa>>gap>>b>>sb;
if(b==0)
{
b=1;continue;
}
if(!p.count(sa)) p[sa]=sa,d[sa]=1;//对节点的初始化
if(!p.count(sb)) p[sb]=sb,d[sb]=1;//对节点的初始化
string ra=findd(sa);string rb=findd(sb);
if(ra==rb) continue;//防止输入环
p[rb]=ra; //将b的父节点插入到a的父节点下面
d[rb]=b/d[sb]*d[sa]; //对b父节点到a父节点的距离的计算(见下图)
}
for(int i=0;i<m;i++) //询问
{
string sa,sb,ra,rb;
double a;
cin>>a>>sa>>gap>>sb;
ra=findd(sa);rb=findd(sb);
if(ra!=rb)//根节点不同就impossible
{
cout<<"impossible"<<endl;
}
else //相同就输出
{
double ans=a*d[sb]/d[sa];//这个公式就是根据到父节点的距离计算两者关系(见上图)
cout<<ans<<endl;
}
}
}
//对b父节点到a父节点的距离的计算: