链接
https://code.google.com/codejam/contest/3214486/dashboard#s=p2
题意
题意
给定N个表达式,形如:
a+b=3
。
又给出M个表达式,形如:
a+c
。问每一个能否由已知的表达式得到,并给出结果
思路
明显的图论题。
从样例考虑:
对于每一个等式,如:
a+b=3
,其中
a
,
对于上述的3个表达式建图如下:
首先,求
a+c
。从表达式中我们可以看出:
只能求出 a−c=0
求 a+d 。我们已经得到了 a−c=0 ,然后又有 c+d=3 ,于是得到 a+d=3 。
(1) 结合上面的图观察,我们可以得到这样一个结论:当从
x
到
(2) 注意还有一个特殊情况就是: x+x=a , y+y=b ,那么我们可以得到 x+y=a+b2
情况2很好处理,我们现在只需要处理情况1:即存在一条从
x
到
因为图可能有环,写到这里就很迷了:可能从
x
到
然后翻了一下大神的代码:直接BFS。
Step1: 首先,从起点走1条边,可以到达若干个点
S
,将集合
Step2: 然后从
S
中所有点出发,每次走2条边可以到达若干个点
该解法解决了2个问题:
1. 确保从
x
到
2. 避免了直接BFS带来的可能不会从奇数环绕一圈的问题
代码
#include <bits/stdc++.h>
using namespace std;
inline int in() {int x; scanf("%d", &x); return x;}
#define pr(x) {cout << #x << ' ' << x << endl;}
const int maxn = 20000 + 5;
struct Edge {
int u, v, w;
Edge() {}
Edge(int a, int b, int c) : u(a), v(b), w(c) {}
bool operator < (Edge& rh) {
return w < rh.w;
}
};
int n, m, vn;
unordered_map<string, int> si;
unordered_map<int, string> is;
vector<Edge> edges;
vector<int> G[maxn];
int vis[maxn];
void AddDoubleEdge(int u, int v, int w) {
edges.push_back(Edge(u, v, w));
G[u].push_back(edges.size() - 1);
edges.push_back(Edge(v, u, w));
G[v].push_back(edges.size() - 1);
}
int Hash(string s) {
if (si.find(s) == si.end()) {
si[s] = ++vn;
is[vn] = s;
}
return si[s];
}
int StringToInt(string s) {
int flag = 1, i = 0;
if (s[0] == '-') {
flag = -1;
i = 1;
}
int len = s.length(), x = 0;
for (i; i < len; i++) {
x *= 10;
x += s[i] - '0';
}
return x * flag;
}
void Handle(string s) {
int pos = s.find('+');
int pos2 = s.find('=');
string pre = s.substr(0, pos);
string af = s.substr(pos + 1, pos2 - pos - 1);
string eq = s.substr(pos2 + 1, s.length() - 1 - pos2);
int pren = Hash(pre);
int afn = Hash(af);
int eqn = StringToInt(eq);
AddDoubleEdge(pren, afn, eqn);
}
pair<int, int> HandleRes(string s) {
int pos = s.find('+');
string pre = s.substr(0, pos);
string af = s.substr(pos + 1, s.length() - 1- pos);
int x = -1, y = -1;
if (si.find(pre) != si.end()) x = si[pre];
if (si.find(af) != si.end()) y = si[af];
return make_pair(x, y);
}
void Read() {
n = in();
string s;
for (int i = 0; i < n; i++) {
cin >> s;
Handle(s);
}
}
void Init() {
vn = 0;
while (edges.size()) edges.pop_back();
is.clear();
si.clear();
for (int i = 1; i < maxn; i++) {
while (G[i].size())
G[i].pop_back();
}
}
void print_graph() {
for (int i = 1; i <= vn; i++) {
cout << is[i] << ": ";
for (int j = 0; j < G[i].size(); j++) {
cout << is[edges[G[i][j]].v] << ',' << edges[G[i][j]].w << ' ';
}
cout << endl;
}
}
int BFS(int u, int target) {
int vis[maxn];
memset(vis, 0, sizeof(vis));
queue<pair<int, int>> Q;
for (int i = 0; i < G[u].size(); i++) {
Edge e = edges[G[u][i]];
vis[e.v] = 1;
Q.push(make_pair(e.v, e.w));
}
while (!Q.empty()) {
pair<int, int> now = Q.front(); Q.pop();
if (now.first == target) {
return now.second;
}
for (int i = 0; i < G[now.first].size(); i++) {
Edge e = edges[G[now.first][i]];
pair<int, int> next = make_pair(e.v, e.w);
for (int j = 0; j < G[next.first].size(); j++) {
Edge ee = edges[G[next.first][j]];
if (!vis[ee.v]) {
vis[ee.v] = 1;
Q.push(make_pair(ee.v, now.second - next.second + ee.w));
}
}
}
}
return -1;
}
void Solve() {
m = in();
while (m--) {
string s;
cin >> s;
pair<int, int> pii = HandleRes(s);
if (pii.first == -1 || pii.second == -1) continue;
int t = BFS(pii.first, pii.second);
if (t != -1) {
cout << is[pii.first] << '+' << is[pii.second] << '=' << t << endl;
} else {
int a = BFS(pii.first, pii.first);
int b = BFS(pii.second, pii.second);
if (a != -1 && b != -1)
cout << is[pii.first] << '+' << is[pii.second] << '=' << (a + b) / 2 << endl;
}
}
}
int main() {
int T = in(), kase = 0;
while (T--) {
Init();
Read();
printf("Case #%d:\n", ++kase);
Solve();
}
return 0;
}