Round C APAC Test 2017 Problem C. Evaluation

Problem C. Evaluation


Given an unordered list of assignment statements, write a program to determine whether the assignment statements can be put in some order in which all variables can be evaluated.

For our problem, an assignment statement will consist of an assignment variable, an assignment operator, and an expression, in that order. Statements will be evaluated one at a time, in the order you choose for them. A variable can be evaluated if and only if it has been the assignment variable of a previous assignment statement.

To simplify the problem, all the expressions are single function calls. Functions can take an arbitrary number of arguments, including zero; a function with zero arguments is always valid, and a function with variable arguments is valid as long as all of the variables are evaluatable.

For example, for the following list of assignment statements:

a=f(b,c)
b=g()
c=h()

this is one order that makes every statement valid:

b=g()
c=h()
a=f(b,c)

This is because: (1) b and c can be evaluated because the expressions g() and h() don't depend on any variables; and (2)a can also be evaluated because expression a depends on b and c, which are evaluatable.

However, the order

b=g()
a=f(b,c)
c=h()

would not be valid, because f(b, c) has variable c as an argument, but variable c has not been an assignment variable yet.

Another example is: a=f(a). This list of statements can't be evaluated because the expression f(a) depends on the variable a itself, which makes it impossible to evaluate the statement.

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 an integer N: the number of assignment statements. Then,N lines follow. Each contains one assignment statement.

Each assignment statement consists of three parts: the assignment variable, the assignment operator, and the expression, with no spaces in between. The assignment operator is always =. All expressions consist of a function name, then (, then zero or more comma-separated variable names, then ). All variables and function names consist of one or more lowercase English alphabet letters. No variable has the same name as a function. No variable will appear more than once as the assignment variable. However, variables may appear more than once in various functions (even within the same function), and functions may appear more than once.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is GOOD if all variables are evaluatable or BAD otherwise.

Limits

1 ≤ T ≤ 20.
All functions take between 0 and 10 arguments, inclusive. All variable names consist of between 1 and 20 lowercase English alphabet letters.

Small dataset

1 ≤ N ≤ 100.

Large dataset

1 ≤ N ≤ 1000.

Sample


Input 
 

Output 
 
4
3
a=f(b,c)
b=g()
c=h()
2
a=f(b)
b=f(a)
2
aaa=foo(x,y)
bbb=bar(aaa,bbb)
2
x=f()
y=g(x,x)
Case #1: GOOD
Case #2: BAD
Case #3: BAD
Case #4: GOOD

Solution

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <list>
#include <iterator>
#include <unordered_set>
#include <unordered_map>
using namespace std;

typedef long long ll;

bool get_res(unordered_map<string, unordered_set<string> >& edges, unordered_map<string, int>& indegrees)
{
    stack<string> s;
    int count = 0;

    for (auto& it : indegrees)
        if (it.second == 0)
            s.push(it.first);

    while (!s.empty())
    {
        auto& l = edges[s.top()];
        s.pop();
        count++;

        for (auto& it : l)
        {
            if (--indegrees[it] == 0)
                s.push(it);
        }
    }

    return count == edges.size();
}

int main(int argc, char* argv[])
{
#ifndef TEST
    if (argc != 2)
    {
        cout << "Invalid input" << endl;
        return 1;
    }

    string input = argv[1];
    string output = input.substr(0, input.length() - 2) + "out";
    freopen(input.c_str(), "r", stdin);
    freopen(output.c_str(), "w", stdout);
#endif

    int T, N;
    string assignment;

    cin >> T;
    for (int i = 1; i <= T; i++)
    {
        cin >> N;
        bool flag = true;
        unordered_map<string, unordered_set<string> > edges;
        unordered_map<string, int> indegrees;
        for (int j = 0; j < N; j++)
        {
            cin >> assignment;
            string left, right;
            int start = 0;
            for (int end = 1; end < assignment.length(); end++)
            {
                if (assignment[end] == '=')
                {
                    left = assignment.substr(start, end - start);
                    indegrees[left] = 0;
                }
                else if (assignment[end] == '(')
                {
                    start = end + 1;
                }
                else if (assignment[end] == ',' || assignment[end] == ')')
                {
                    if (assignment[end - 1] == '(')
                        break;

                    right = assignment.substr(start, end - start);
                    if (right == left)
                    {
                        flag = false;
                        break;
                    }

                    if (edges[right].find(left) == edges[right].end())
                    {
                        indegrees[left]++;
                        edges[right].insert(left);
                    }

                    start = end + 1;
                }
            }

            if (!flag)
                break;
        }

#ifdef TEST
        for (auto& it : indegrees)
        {
            cout << it.first << "->";
            for (auto& e : edges[it.first])
                cout << e << " ";
            cout << endl;
        }
#endif

        if (flag)
            flag = get_res(edges, indegrees);

        cout << "Case #" << i << ": " << (flag ? "GOOD" : "BAD") << endl;
    }

    fclose(stdin);
    fclose(stdout);

    return 0;
}


Note


拓扑排序问题。


Reference


https://code.google.com/codejam/contest/6274486/dashboard#s=p2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EnjoyCodingAndGame

愿我的知识,成为您的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值