题目:
Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.
Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is: vector < pair < string, string> > equations, vector& values, vector < pair < string, string> > queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector.
According to the example above:
equations = [ [“a”, “b”], [“b”, “c”] ],
values = [2.0, 3.0],
queries = [ [“a”, “c”], [“b”, “a”], [“a”, “e”], [“a”, “a”], [“x”, “x”] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
这个题还是挺有意思的。
将每个分数当做图中的一个节点,边权为乘数的权值。
基础节点共有2n个(输入条件为n个分数),即这n个分数和这n个分数的倒数。
图中所有的新增节点的产生只有两种途径:
1.基础节点(基础分数)*基础分数(边)得到一个新增节点(新增分数)
2.新增节点(新增分数)*基础分数(边)得到一个新增节点(新增分数)
也就是说,新增节点是不可以作为边的,因为即便你想让新增节点作为边,这个分数的值在dfs之前是不知道的,所以也没办法作为边。
class Solution {
#define N 11111
#define M 111111
public:
map< pair<string, string>, int> mp;
double ans[N];
bool vis[N];
int cnt;
int ts;
int head[N], nxt[M], to[M];
double len[M];
void add(int u, int v, double w) {
to[ts] = v; len[ts] = w; nxt[ts] = head[u]; head[u] = ts++;
//cout << u << " " << v << " " << w << endl;
}
vector<double> calcEquation(vector< pair<string, string> > equations, vector<double>& values, vector< pair<string, string> > queries) {
memset(head, -1, sizeof head);
memset(vis, 0, sizeof vis);
mp.clear();
cnt = 0;
ts = 0;
pair<string, string> pr;
int n = equations.size();
for (int i = 0; i < n; i++)
if (mp[equations[i]] == 0) {
mp[equations[i]] = ++cnt;
add(0, mp[equations[i]], values[i]);//multiply
pr.first = equations[i].second;
pr.second = equations[i].first;
equations.push_back(pr);
values.push_back(1.0 / values[i]);
if (mp[pr] == 0) mp[pr] = ++cnt;
add(0, mp[pr], 1.0 / values[i]);//divide
}
int m = equations.size();
for (int i = 0; i < equations.size(); i++) {//注意这两层循环
for (int j = 0; j < m; j++) {
if (i == j) continue;
if (equations[i].first == equations[j].second) {//multiply
pr.first = equations[j].first;
pr.second = equations[i].second;
if (mp[pr] == 0) {
mp[pr] = ++cnt;
equations.push_back(pr);//新增
}
add(mp[equations[i]], mp[pr], values[j]);
}
if (equations[i].second == equations[j].first) {//multiply
pr.first = equations[i].first;
pr.second = equations[j].second;
if (mp[pr] == 0) {
mp[pr] = ++cnt;
equations.push_back(pr);//新增
}
add(mp[equations[i]], mp[pr], values[j]);
}
}
}
ans[0] = 1.0;
vis[0] = true;
dfs(0);
vector<double> rt;
for (int i = 0; i < queries.size(); i++) {
if (mp[queries[i]] == 0) rt.push_back(-1.0);
else rt.push_back(ans[mp[queries[i]]]);
}
return rt;
}
void dfs(int x) {
for (int i = head[x]; ~i; i = nxt[i]) {
if (!vis[to[i]]) {
ans[to[i]] = ans[x] * len[i];
vis[to[i]] = true;
dfs(to[i]);
}
}
}
};
这题在写测试代码的时候挺恶心的,把测试代码也放上来吧。
int main() {
Solution s;
vector< pair<string, string> > vequations;
vequations.push_back(make_pair("x1", "x2"));
vequations.push_back(make_pair("x2", "x3"));
vequations.push_back(make_pair("x3", "x4"));
vequations.push_back(make_pair("x4", "x5"));
vector<double> values;
values.push_back(3.0);
values.push_back(4.0);
values.push_back(5.0);
values.push_back(6.0);
vector< pair<string, string> > queries;
queries.push_back(make_pair("x1", "x5"));
queries.push_back(make_pair("x5", "x2"));
queries.push_back(make_pair("x2", "x4"));
queries.push_back(make_pair("x2", "x2"));
queries.push_back(make_pair("x2", "x9"));
vector<double> ans;
ans = s.calcEquation(vequations, values, queries);
for (int i = 0; i < ans.size(); i++) cout << ans[i] << endl;
return 0;
}