题目:
今天这道题是中等题我是完全没有想到的。对于目前对并查集不太了解的我来说绝对是困难题。
我自己是写不出代码的,我就大致说说我的理解和题解的做法。
思路:
这种题我们用高中知识也知道,要转换成有共通的变量,然后用相同的变量带入求值。比如a = 3c,b=2c,那么a/b = 3/2。
那么题解转换成共同变量的做法就是图。用根节点表示可以转换成的变量,路径上的权值代表比例。
之后,使用了"并查集"的做法,优化算法,不断更新得到最优解。
C++官方题解代码(我是没怎么完全看懂的,寒假的好好补一补课了)
class Solution {
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
int nvars = 0;
unordered_map<string, int> variables;
int n = equations.size();
for (int i = 0; i < n; i++) {
if (variables.find(equations[i][0]) == variables.end()) {
variables[equations[i][0]] = nvars++;
}
if (variables.find(equations[i][1]) == variables.end()) {
variables[equations[i][1]] = nvars++;
}
}
// 对于每个点,存储其直接连接到的所有点及对应的权值
vector<vector<pair<int, double>>> edges(nvars);
for (int i = 0; i < n; i++) {
int va = variables[equations[i][0]], vb = variables[equations[i][1]];
edges[va].push_back(make_pair(vb, values[i]));
edges[vb].push_back(make_pair(va, 1.0 / values[i]));
}
vector<double> ret;
for (const auto& q: queries) {
double result = -1.0;
if (variables.find(q[0]) != variables.end() && variables.find(q[1]) != variables.end()) {
int ia = variables[q[0]], ib = variables[q[1]];
if (ia == ib) {
result = 1.0;
} else {
queue<int> points;
points.push(ia);
vector<double> ratios(nvars, -1.0);
ratios[ia] = 1.0;
while (!points.empty() && ratios[ib] < 0) {
int x = points.front();
points.pop();
for (const auto [y, val]: edges[x]) {
if (ratios[y] < 0) {
ratios[y] = ratios[x] * val;
points.push(y);
}
}
}
result = ratios[ib];
}
}
ret.push_back(result);
}
return ret;
}
};
害。你管这叫中等题。。。。