Addition

Problem

Six years ago, a robot, Bob, with infant's intelligence has been invented by an evil scientist, Alice.

Now the robot is six years old and studies in primary school. Addition is the first operation he learned in math. Due to his strong reasoning ability, he could now conclude a+b=12 from a=2 and b=10.

Alice wanted to test Bob's addition skills. Some equations were given to Bob in form of a=2, b=10, c=4, and Bob has to find out the answers of questions like a+b, a+c, etc.

Alice checked Bob's answers one by one in the test papers, and no mistake has been found so far, but Alice lost the given equations after a cup of coffee poured on them. However she has some of Bob's correct answers, e.g. a+b=12, a+c=6, c+d=5. She wants to continue with the checkable equations, e.g. b+d=11 could be concluded by a+b=12, a+c=6, c+d=5, and thus the question b+d is checkable.

To prevent the artificial intelligence technology from being under the control of Alice, you disguised yourself as her assistant. Now Alice wants you to figure out which of the rest of questions are checkable and their answers.

Input

The first line of the input gives the number of test cases, TT test cases follow.

The first line of each test case contains a single integer N: the number of correctly answered questions. Each of the next N lines contain one correctly answered question in the form "x+y=z", where x and y are names of variables and z is a decimal integer.

The next line contains a single integer Q: the number of remaining questions. Each of the next Q lines contain one question in the form "x+y", where x and y are names of variables.

Output

For each test case, the first line of output contains "Case #x:", where x is the test case number (starting from 1). For each question in the input that was checkable, output a single line with the answer in the form "x+y=z", where x and y are names of variables andz is a decimal integer. Questions should be listed in the same order as they were given in the input. Please do NOT ignore duplicated questions, since Alice would fire you if you pointed any mistake of hers.

Limits

Names of variables are strings of lowercase English letters. Each name contains at most 10 characters.

-200000 ≤ z ≤ 200000

There is no contradiction in the answered questions.

Small dataset

T ≤ 10

N ≤ 10

Q ≤ 10

Large dataset

T ≤ 3

N ≤ 5000

Q ≤ 5000

Sample


Input 
 

Output 
 
2
2
apple+banana=10
coconut+coconut=12
5
apple+banana
apple+banana
apple+apple
banana+apple
peach+apple
3
a+b=3
b+c=3
c+d=3
4
a+c
a+d
b+c
b+d

Case #1:
apple+banana=10
apple+banana=10
banana+apple=10
Case #2:
a+d=3
b+c=3

将变量抽象为图顶点,等式抽象为图的边,看能否有奇数条边的通路即可。使用BFS搜索。

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <unordered_map>
#include <queue>
#include <sstream>

using namespace std;

struct GEdge
{
    int To;         // the other end
    int Value;      // value of the edge
    GEdge(int to, int val) : To(to), Value(val) {}
};

typedef vector<GEdge> EdgeArray;
vector<EdgeArray> g_Graph;              // all edges from node i
unordered_map<string, int> g_Nodes;     // all nodes
int g_NodeCount;                        // used to generate the node index

void add_edge(int node1, int node2, int val)
{
    // undirected graph
    g_Graph[node1].push_back(GEdge(node2, val));
    g_Graph[node2].push_back(GEdge(node1, val));
}

int get_node(const string &name) // fetch or create a node
{
    if (g_Nodes.count(name) > 0)
        return g_Nodes[name];
    return (g_Nodes[name] = g_NodeCount++);
}

bool bfs_search_path(int &val, int from, int to)
{
    vector<bool> visited(g_NodeCount, false);
    queue<GEdge> Q;
    for (auto edge : g_Graph[from])
        Q.push(edge);
    while (!Q.empty())
    {
        GEdge cur = Q.front();
        Q.pop();
        int node = cur.To;
        if (node == to)
        {
            val = cur.Value;
            return true;
        }
        for (auto e : g_Graph[node])
        {
            for (auto ee : g_Graph[e.To]) // two loops to find odd edges
            {
                if (visited[ee.To])
                    continue;
                visited[ee.To] = true;
                Q.push(GEdge(ee.To, cur.Value - e.Value + ee.Value));
            }
        }
    }
    return false;
}

void work_single(istream &input, ostream &output)
{
    int N;
    input >> N;

    // clear graph
    g_Graph.clear();
    g_Nodes.clear();
    g_NodeCount = 0;
    g_Graph.resize(N * 2);

    // read and build graph
    for (int i = 0; i < N; i++)
    {
        string line;
        input >> line;
        // find +,= position
        size_t j;
        for (j = 0; j < line.length(); j++)
        {
            if (line[j] == '+' || line[j] == '=')
                line[j] = ' ';
        }
        string name1, name2;
        int val;
        istringstream line_stream(line);
        line_stream >> name1 >> name2 >> val;
        // add edge
        int node1 = get_node(name1);
        int node2 = get_node(name2);
        add_edge(node1, node2, val);
    }
    
    int Q;
    input >> Q;
    for (int i = 0; i < Q; i++)
    {
        string line;
        input >> line;
        // find +
        size_t j;
        for (j = 0; j < line.length(); j++)
        {
            if (line[j] == '+')
                break;
        }
        string name1 = line.substr(0, j);
        string name2 = line.substr(j + 1, line.length() - j - 1);
        if (g_Nodes.count(name1) == 0 || g_Nodes.count(name2) == 0)
            continue;
        int node1 = get_node(name1);
        int node2 = get_node(name2);
        int val;
        if (bfs_search_path(val, node1, node2))
            output << line << "=" << val << endl;
    }
}

void work(istream &input, ostream &output)
{
    int case_count;
    input >> case_count;
    for (int i = 0; i < case_count; i++)
    {
        output << "Case #" << i + 1 << ":" << endl;
        work_single(input, output);
    }
}

int main(int argc, char *argv[])
{
    bool use_stdio = false;
    if (use_stdio)
        work(cin, cout);
    else
    {
        ifstream input("C-large-practice.in");
        ofstream output("C-large-practice.out");
        work(input, output);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值