这种题目中给到是有向向量的题目,基本就要想到图的思想。
一旦路径中有了数值(权值),就要想到最小路径相关的算法,其中floyd算法就是用来求最小路径的。
floyd算法:需要两个矩阵,矩阵D是存放初始化某个节点到另一个节点最小权值,矩阵P用来存放一个节点到另一个节点的走法。然后就是去求解最短路径的矩阵,需要三层for循环,第一层是中转点k,第二层是路径的起始点v,第三层是路径的终点w。在操作的过程种不断的去对比直接从v走到w和从v到k再到w哪一个更快一些,更新更快的数据(包括权值,和P矩阵中的中转值)。
对于本题而言,难点在于D矩阵的创建,首先需要遍历一遍数组来获得所有的元素的个数vals_num,并用一个hashmap来存贮每一个节点对应的序号。然后再去创建矩阵D,遍历一遍数组,然后用map转换为序号,存放两个节点间权值,默认为-1。floyd操作的时候也需要修改,应该是判断D[v][k]和D[v][w]是否全大于0且D[v][w]小于0才去更新。
class Solution {
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
//首先通过一次遍历找出所有出现的节点的个数,然后利用这些节点去构成一个图
int vals_num=0,n=equations.size();
unordered_map<string,int> check;
for(auto& k:equations)//通过一次遍历输入的数组,进行元素的编号,并统计元素的总个数
{
if(check.find(k[0])==check.end())check[k[0]]=vals_num++;
if(check.find(k[1])==check.end())check[k[1]]=vals_num++;
}
//下面开始初始化权值矩阵D和最短路径矩阵P
vector<vector<double>> D(vals_num,vector<double>(vals_num,-1.0));
for(int i=0;i<n;++i)
{
int va=check[equations[i][0]],vb=check[equations[i][1]];//va和vb表示equations数组第i对
D[va][va]=1.0;//自己除自己为1.0
D[vb][vb]=1.0;
//0和1元素对应元素序号
D[va][vb]=values[i];
D[vb][va]=1/values[i];
}
//通过floyd(弗洛伊德算法)模板,进行最小权值与最短路径的查找
Floydfun(D);
vector<double> ans;
for(auto&k:queries)
{
int va=-1,vb=-1;
if(check.find(k[0])!=check.end())va=check[k[0]];
else {
ans.push_back(-1.0);
continue;
}
if(check.find(k[1])!=check.end())vb=check[k[1]];
else{
ans.push_back(-1.0);
continue;
}
ans.push_back(D[va][vb]<0?-1.0:D[va][vb]);
}
return ans;
}
private:
void Floydfun(vector<vector<double>>& D)
{
int n=D.size();
for(int k=0;k<n;++k)//中转点
{
for(int v=0;v<n;++v)//路径起始点
{
for(int w=0;w<n;++w)//路径的终止点
{
if(D[v][w]<0&&(D[v][k]>0&&D[k][v]>0))
{
D[v][w]=D[v][k]*D[k][w];//将权值更新为最小权值
}
}
}
}
}
};