CSP CCF:202009-3 点亮数字人生 (C++)

博客内容涉及利用C++实现有向无环图(DAG)的拓扑排序,以及在该场景下进行逻辑门计算。通过解析输入的逻辑门器件及其连接关系,构建邻接表,并检查是否存在环路。在无环路的情况下,根据层级对器件进行排序,然后逐层计算器件的输出,最终输出指定输入条件下的结果。博客中还讨论了代码中出现的问题及改进过程,包括细节处理和性能优化。
摘要由CSDN通过智能技术生成

纯记录一下, 感兴趣的请移步大佬博客

题目来源

http://118.190.20.162/view.page?gpid=T111

大佬博客

层级:https://blog.csdn.net/qq_44528283/article/details/109501132
拓扑排序:https://blog.csdn.net/qq_44528283/article/details/113446330

层级: 根据大佬的代码写得 (0分)(自己没注意细节)

#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>

using namespace std;

struct device {
    int id;                  // 器件编号
    string type;             // 器件类型
    bool ct;                 // 器件是否构建好了
    int level;               // 器件层级
    int output;              // 器件输出
    vector<string> input_str;// 器件输入的器件/输入
    vector<int> input;       // 器件此次的输入
    vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了

    device (){
        level = -1;
        ct = false;
    }

    compute() {
        int result = input[0];
        if (type == "NOT") {
            result = !result;
        }
        else if (type == "AND") {
            for (int i = 1; i < input.size(); ++i) {
                result &= input[i];
            }
        }
        else if (type == "OR") {
            for (int i = 1; i < input.size(); ++i) {
                result |= input[i];
            }
        }
        else if (type == "XOR") {
            for (int i = 1; i < input.size(); ++i) {
                result ^= input[i];
            }
        }
        else if (type == "NAND") {
            for (int i = 1; i < input.size(); ++i) {
                result &= input[i];
            }
            result = !result;
        }
        else {
            for (int i = 1; i < input.size(); ++i) {
                result |= input[i];
            }
            result = !result;
        }

        output = result;
    }
};

int strToNum(string input_str) {
    /*
    int result = 0;
    for (int i = 1; i < input_str.size(); ++i) {
        result = result * 10 + (input_str[i] - '0');
    }

    return result;
    */
    int result;
    string str = input_str.substr(1); //截取I/O后面的数字字符串
    stringstream ss;
    ss << str;
    ss >> result;
    return result;
}

bool cmp(device d1, device d2) {
    return d1.level < d2.level;  // <
}

int main() {
    int Q;
    cin>>Q;

    for (int q = 0; q < Q; ++q) {
        int M, N;
        cin>>M>>N;

        // 器件
        device dce[N+2];

        // 输入器件信息
        for (int i = 1; i <= N; ++i) {
            string FUNC;
            int k;
            cin>>FUNC>>k;

            dce[i].type = FUNC;
            dce[i].id = i;
            for (int j = 0; j < k; ++j) {
                string inInfo;
                cin>>inInfo;
                dce[i].inputDecFlag.emplace_back(false);
                dce[i].input_str.emplace_back(inInfo);

            }
        }

        int S;
        cin>>S;

        // 输入
        //vector<vector<int> > input;
        int input[S][M];
        //vector<vector<int> > outputDce;
        vector<int> outputDce[S];

        // 输入每次输入的信息
        for (int i = 0; i < S; ++i) {
            //input.emplace_back(vector<int>());
            for (int j = 0; j < M; ++j) {
                int tmp;
                cin>>tmp;
                //input[i].emplace_back(tmp);
                input[i][j] = tmp;
            }
        }
        // 输入每次输出的要求
        for (int i = 0; i < S; ++i) {
            int num;
            cin>>num;
            //outputDce.emplace_back(vector<int>());
            for (int j = 0; j < num; ++j) {
                int tmp;
                cin>>tmp;
                outputDce[i].emplace_back(tmp);
            }
        }

        //
        bool loop = false;

        // 构建设备之间的联系
        while (1) {
            int preState[N + 1];
            // 保留前一次的层级
            for (int i = 1; i <= N; ++i) {
                preState[i] = dce[i].level;
            }
            // 更新层级
            int cont = 0; // 记录是否有更新
            for (int i = 1; i <= N; ++i) {
                // 当前设备未构建完成
                if ( !dce[i].ct) {
                    ++cont;
                    // 对每个输入设备
                    for (int j = 0; j < dce[i].input_str.size(); ++j) {
                        // 当前设备未入册
                        if ( !dce[i].inputDecFlag[j]) {
                            string str = dce[i].input_str[j];
                            int preNum = strToNum(str);
                            // 直接接输入
                            if (str[0] == 'I') {
                                dce[i].inputDecFlag[j] = true;
                                //dce[preNum].level = max(0, dce[preNum].level);
                                dce[i].level = max(0, dce[i].level);
                            }
                            // 从其他设备接入
                            else {
                                // 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
                                if (dce[preNum].ct) {
                                    dce[i].inputDecFlag[j] = true;
                                    //dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
                                    dce[i].level = max(dce[preNum].level + 1, dce[i].level);
                                }
                            }
                        }
                    }

                    // 如果当前设备输入都已入册
                    for (int j = 0; j < dce[i].input_str.size(); ++j) {
                        if (dce[i].inputDecFlag[j] == false) {  // 未全部入册
                            break;
                        }
                        if (j == dce[i].input_str.size() - 1) {  // 全入册了
                            dce[i].ct = true;
                        }
                    }
                }
            }
            // 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
            if (cont == 0) {
                break;
            }
            // 判断是否有环路
            for (int i = 1; i <= N; ++i) {
                if (preState[i] != dce[i].level) {
                    break;
                }
                if (i == N) {
                    loop = true;
                }
            }
            // 有环路
            if (loop) {
                break;
            }
        }

        // 判断是否有环路
        if (loop) {
            cout<<"LOOP"<<endl;
        }
        else {
            // 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
            sort(dce, dce+N, cmp) ;  // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦

            for (int i = 0; i < S; ++i) {
                map<int, int> id2output;
                // 计算
                // 对每个设备
                for (int j = 1; j <= N; ++j) {
                    for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
                        string str = dce[j].input_str[sIndex];
                        if (str[0] == 'I') {
                            dce[j].input.emplace_back(input[i][strToNum(str) - 1]);  // - 1
                        }
                        else {
                            dce[j].input.emplace_back(dce[strToNum(str)].output);
                        }
                    }
                    // 计算
                    dce[j].compute();
                    id2output[j] = dce[j].output;
                }

                // 输出
                for (int j = 0; j < outputDce[i].size(); ++j) {
                    cout<<id2output[outputDce[i][j]]<<" ";
                }
                cout<<endl;

                id2output.clear();
                for (int j = 1; j <= N; ++j) {
                    dce[j].input.clear();
                }
            }
        }
    }


    return 0;
}

层级: 60分, 运行超时, !细节!

照着大佬的代码,改了很多地方。几乎除了变量名外,其他都变了。
我猜主要原因是 sort()那里,我写的是+N, 不是 +N+2。

#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>

using namespace std;

struct device {
    int id;                  // 器件编号
    string type;             // 器件类型
    bool ct;                 // 器件是否构建好了
    int level;               // 器件层级
    int output;              // 器件输出
    vector<string> input_str;// 器件输入的器件/输入
    vector<int> input;       // 器件此次的输入
    vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了

    device (){
        level = -1;
        ct = false;
    }

    compute()
    {
        int result = input[0];
        if(type=="NOT") result=!input[0];
		else if(type=="AND")
        {
            for(int i=1;i<input.size();i++)
            {
                result &= input[i];
            }
        }
		else if(type=="OR")
        {
            for(int i=1;i<input.size();i++)
            {
                result |= input[i];
            }
        }
		else if(type=="XOR")
        {
            for(int i=1;i<input.size();i++)
            {
                result ^= input[i];
            }
        }
        else if(type=="NAND")
        {
            for(int i=1;i<input.size();i++)
            {
                result &= input[i];
            }
            result = !result;
        }
        else
        {
            for(int i=1;i<input.size();i++)
            {
                result |= input[i];
            }
            result = !result;
        }
        output = result;
    }
};

int strToNum(string s) {
    int result;
    string str = s.substr(1); //截取I/O后面的数字字符串
    stringstream ss;
    ss << str;
    ss >> result;
    return result;
}

bool cmp(device d1, device d2) {
    return d1.level < d2.level;  // <
}

int main() {
    int Q;
    cin>>Q;

    for (int q = 0; q < Q; ++q) {
        int M, N;
        cin>>M>>N;

        // 器件
        device dce[N];

        // 输入器件信息
        for (int i = 0; i < N; ++i) {
            string FUNC;
            int k;
            cin>>FUNC>>k;

            dce[i].type = FUNC;
            dce[i].id = i +1;
            for (int j = 0; j < k; ++j) {
                string inInfo;
                cin>>inInfo;
                dce[i].inputDecFlag.emplace_back(false);
                dce[i].input_str.emplace_back(inInfo);

            }
        }

        int S;
        cin>>S;

        // 输入
        //vector<vector<int> > input;
        int input[S][M];
        //vector<vector<int> > outputDce;
        vector<int> outputDce[S];

        // 输入每次输入的信息
        for (int i = 0; i < S; ++i) {
            //input.emplace_back(vector<int>());
            for (int j = 0; j < M; ++j) {
                //int tmp;
                cin>>input[i][j];
                //input[i].emplace_back(tmp);
                //input[i][j] = tmp;
            }
        }
        // 输入每次输出的要求
        for (int i = 0; i < S; ++i) {
            int num;
            cin>>num;
            //outputDce.emplace_back(vector<int>());
            for (int j = 0; j < num; ++j) {
                int tmp;
                cin>>tmp;
                outputDce[i].emplace_back(tmp);
            }
        }

        //
        bool loop = false;
        int cont = 0; // 记录是否有更新
        int preState[N + 1];
        // 构建设备之间的联系
        while (1) {
            cont = 0;
            // 保留前一次的层级
            for (int i = 0; i < N; ++i) {
                preState[i] = dce[i].level;
            }
            // 更新层级

            for (int i = 0; i < N; ++i) {
                // 当前设备未构建完成
                if ( !dce[i].ct) {
                    ++cont;
                    // 对每个输入设备
                    for (int j = 0; j < dce[i].input_str.size(); ++j) {
                        // 当前设备未入册
                        int run_level;
                        if ( !dce[i].inputDecFlag[j]) {
                            string str = dce[i].input_str[j];
                            int preNum = strToNum(str);

                            // 直接接输入
                            if (str[0] == 'I') {
                                run_level = 0;
                                dce[i].inputDecFlag[j] = true;
                                //dce[preNum].level = max(0, dce[preNum].level);
                                //dce[i].level = max(0, dce[i].level);
                            }
                            // 从其他设备接入
                            else if (str[0] == 'O') {
                                // 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
                                if (dce[preNum - 1].ct) {
                                    dce[i].inputDecFlag[j] = true;
                                    //dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
                                    //dce[i].level = max(dce[preNum].level + 1, dce[i].level);
                                    run_level = dce[preNum - 1].level + 1;
                                }
                            }
                            if (run_level > dce[i].level) {
                                dce[i].level = run_level;
                            }
                        }
                    }

                    // 如果当前设备输入都已入册
                    for (int j = 0; j < dce[i].inputDecFlag.size(); ++j) {
                        if ( !dce[i].inputDecFlag[j]) {  // 未全部入册
                            break;
                        }
                        if (j == dce[i].input_str.size() - 1) {  // 全入册了
                            dce[i].ct = true;
                        }
                    }
                }
            }
            // 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
            if (cont == 0) {
                break;
            }
            int same_num = 0;
            for (int i = 1; i <= N; ++i) {
                if (preState[i] == dce[i].level) {
                    ++same_num;
                }
            }
            // 有环路
            if (same_num == N) {
                loop = true;
                break;
            }
        }

        // 判断是否有环路
        if (loop) {
            cout<<"LOOP"<<endl;
        }
        else {
            // 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
            sort(dce, dce+N, cmp) ;  // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦

            for (int i = 0; i < S; ++i) {
                map<int, int> id2output;
                // 计算
                // 对每个设备
                for (int j = 0; j < N; ++j) {
                    for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
                        string str = dce[j].input_str[sIndex];
                        if (str[0] == 'I') {
                            dce[j].input.emplace_back(input[i][strToNum(str) - 1]);  // - 1
                        }
                        else {
                            //dce[j].input.emplace_back(dce[strToNum(str)].output);
                            dce[j].input.emplace_back(id2output[strToNum(str)]);
                        }
                    }
                    // 计算
                    dce[j].compute();
                    id2output[dce[j].id] = dce[j].output;
                }

                // 输出
                for (int j = 0; j < outputDce[i].size(); ++j) {
                    cout<<id2output[outputDce[i][j]]<<" ";
                }
                cout<<endl;

                id2output.clear();
                for (int j = 0; j < N; ++j) {
                    dce[j].input.clear();
                }
            }
        }
    }


    return 0;
}

层级:终于100了

改动了一个地方,将i=1->N 改成了 i=0->N-1.

#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>

using namespace std;

struct device {
    int id;                  // 器件编号
    string type;             // 器件类型
    bool ct;                 // 器件是否构建好了
    int level;               // 器件层级
    int output;              // 器件输出
    vector<string> input_str;// 器件输入的器件/输入
    vector<int> input;       // 器件此次的输入
    vector<bool> inputDecFlag;// 器件在对应位置上的输入是否构建好了

    device (){
        level = -1;
        ct = false;
    }

    compute()
    {
        int result = input[0];
        if(type=="NOT") result=!input[0];
		else if(type=="AND")
        {
            for(int i=1;i<input.size();i++)
            {
                result &= input[i];
            }
        }
		else if(type=="OR")
        {
            for(int i=1;i<input.size();i++)
            {
                result |= input[i];
            }
        }
		else if(type=="XOR")
        {
            for(int i=1;i<input.size();i++)
            {
                result ^= input[i];
            }
        }
        else if(type=="NAND")
        {
            for(int i=1;i<input.size();i++)
            {
                result &= input[i];
            }
            result = !result;
        }
        else
        {
            for(int i=1;i<input.size();i++)
            {
                result |= input[i];
            }
            result = !result;
        }
        output = result;
    }
};

int strToNum(string s) {
    int result;
    string str = s.substr(1); //截取I/O后面的数字字符串
    stringstream ss;
    ss << str;
    ss >> result;
    return result;
}

bool cmp(device d1, device d2) {
    return d1.level < d2.level;  // <
}

int main() {
    int Q;
    cin>>Q;

    for (int q = 0; q < Q; ++q) {
        int M, N;
        cin>>M>>N;

        // 器件
        device dce[N];

        // 输入器件信息
        for (int i = 0; i < N; ++i) {
            string FUNC;
            int k;
            cin>>FUNC>>k;

            dce[i].type = FUNC;
            dce[i].id = i +1;
            for (int j = 0; j < k; ++j) {
                string inInfo;
                cin>>inInfo;
                dce[i].inputDecFlag.emplace_back(false);
                dce[i].input_str.emplace_back(inInfo);

            }
        }

        int S;
        cin>>S;

        // 输入
        //vector<vector<int> > input;
        int input[S][M];
        //vector<vector<int> > outputDce;
        vector<int> outputDce[S];

        // 输入每次输入的信息
        for (int i = 0; i < S; ++i) {
            //input.emplace_back(vector<int>());
            for (int j = 0; j < M; ++j) {
                //int tmp;
                cin>>input[i][j];
                //input[i].emplace_back(tmp);
                //input[i][j] = tmp;
            }
        }
        // 输入每次输出的要求
        for (int i = 0; i < S; ++i) {
            int num;
            cin>>num;
            //outputDce.emplace_back(vector<int>());
            for (int j = 0; j < num; ++j) {
                int tmp;
                cin>>tmp;
                outputDce[i].emplace_back(tmp);
            }
        }

        //
        bool loop = false;
        int cont = 0; // 记录是否有更新
        int preState[N];
        // 构建设备之间的联系
        while (1) {
            cont = 0;
            // 保留前一次的层级
            for (int i = 0; i < N; ++i) {
                preState[i] = dce[i].level;
            }
            // 更新层级

            for (int i = 0; i < N; ++i) {
                // 当前设备未构建完成
                if ( !dce[i].ct) {
                    ++cont;
                    // 对每个输入设备
                    for (int j = 0; j < dce[i].input_str.size(); ++j) {
                        // 当前设备未入册
                        int run_level;
                        if ( !dce[i].inputDecFlag[j]) {
                            string str = dce[i].input_str[j];
                            int preNum = strToNum(str);

                            // 直接接输入
                            if (str[0] == 'I') {
                                run_level = 0;
                                dce[i].inputDecFlag[j] = true;
                                //dce[preNum].level = max(0, dce[preNum].level);
                                //dce[i].level = max(0, dce[i].level);
                            }
                            // 从其他设备接入
                            else if (str[0] == 'O') {
                                // 如果这个设备的输入是另一个设备的输出, 且该设备已经构建好了
                                if (dce[preNum - 1].ct) {
                                    dce[i].inputDecFlag[j] = true;
                                    //dce[preNum].level = max(dce[preNum].level + 1, dce[preNum].level);
                                    //dce[i].level = max(dce[preNum].level + 1, dce[i].level);
                                    run_level = dce[preNum - 1].level + 1;
                                }
                            }
                            if (run_level > dce[i].level) {
                                dce[i].level = run_level;
                            }
                        }
                    }

                    // 如果当前设备输入都已入册
                    for (int j = 0; j < dce[i].inputDecFlag.size(); ++j) {
                        if ( !dce[i].inputDecFlag[j]) {  // 未全部入册
                            break;
                        }
                        if (j == dce[i].input_str.size() - 1) {  // 全入册了
                            dce[i].ct = true;
                        }
                    }
                }
            }
            // 没有更新了, 说明当前没有环路, 且设备间的关系构建完成
            if (cont == 0) {
                break;
            }
            int same_num = 0;
            for (int i = 0; i < N; ++i) {  /* enmmm,这里  i = 0->N-1 */
                if (preState[i] == dce[i].level) {
                    ++same_num;
                }
            }
            // 有环路
            if (same_num == N) {
                loop = true;
                break;
            }
        }

        // 判断是否有环路
        if (loop) {
            cout<<"LOOP"<<endl;
        }
        else {
            // 没有环路, 对于每一次的输入 和 指定的输出 来说, 需要进行如下操作
            sort(dce, dce+N, cmp) ;  // !!!很重要!!!, 根据level来排序才能不用每次都考虑当前设备前一个设备的输出啦

            for (int i = 0; i < S; ++i) {
                map<int, int> id2output;
                // 计算
                // 对每个设备
                for (int j = 0; j < N; ++j) {
                    for (int sIndex = 0; sIndex < dce[j].input_str.size(); ++sIndex) {
                        string str = dce[j].input_str[sIndex];
                        if (str[0] == 'I') {
                            dce[j].input.emplace_back(input[i][strToNum(str) - 1]);  // - 1
                        }
                        else {
                            //dce[j].input.emplace_back(dce[strToNum(str)].output);
                            dce[j].input.emplace_back(id2output[strToNum(str)]);
                        }
                    }
                    // 计算
                    dce[j].compute();
                    id2output[dce[j].id] = dce[j].output;
                }

                // 输出
                for (int j = 0; j < outputDce[i].size(); ++j) {
                    cout<<id2output[outputDce[i][j]]<<" ";
                }
                cout<<endl;

                id2output.clear();
                for (int j = 0; j < N; ++j) {
                    dce[j].input.clear();
                }
            }
        }
    }


    return 0;
}


拓扑排序(100)

字符串转数字

#include <iostream>
#include <algorithm>
string s = "A123";
// 需要加(char *), 避免出错。 因为s指向的是常量, 常量不能直接赋值给char*类型。 看解释: https://blog.csdn.net/ku360517703/article/details/8180818
char *cs = (char*)s.substr(1).c_str();  // char *cs = (char*)s.substr(1, s.length() - 1).c_str();
int num_1 = atoi(cs);  // 123
int num_2 = atoi(s.substr(1, s.length() - 1).c_str()) ;  // 123

虽然看了大佬代码好几遍。但每次自己尝试去写,总会有些疑惑的地方,于是看一遍,重写一遍。第三遍重写终于把完整的代码和思路写完啦,并且一次就写出来了满分~ 不得不说大佬写的博客真的让人受益匪浅。

学到的知识点:
1、图、邻接表的构建。
2、有向无环图的检测与广搜  ————— ! 入度很重要 !。
3、mencpy()、memset()、fill、atoi() 的使用

自己再随意记录记录:
1、 注意全局定义时的MAXN 和 MAXM的使用
2、弄清楚tab的含义, tab[i][j]是 i 指向 j, 那 i 就有可能是 输入、也可能是器件, j 只可能是器件。
3、注意各下标的含义, 注意有没有包含输入。 同时,最好是在输入或者说初始化就给弄好,不要搞到要计算结果的时候再去+1、-1的,这样很容易弄混淆、弄糊涂。
4、全局变量要记得清理清理, clear clear。
5、多多练题, 加油~

贴上代码:

#include <iostream>
#include <vector>
#include <queue>  // queue
#include <string.h>  // memcpy ...
#include <algorithm>  // atoi、 fill

using namespace std;

// 常量
const int MAXK = 5;
const int MAXN = 501;
const int MAXM = 2501;  // k * N
const int MAXS = 100001;

// 器件
vector<int> tab[MAXN + MAXM]; // 邻接表(包含输入和器件) dce[i][j]: i->j
string type[MAXN];            // 每个器件的类型
int InD[MAXN + MAXM];         // 每个器件和输入的入度

// 输入
vector<vector<int> > input;     // 输入
vector<vector<int> > outputDev;  // 每个输入要求输出的器件编号

// 输出
int output[MAXN + MAXM];  // 输入和器件的结果


// 判断邻接表是不是有向无环图
bool topologicalSort(int  N, int M) {
    int curInD[MAXN + MAXM];
    memcpy(curInD, InD, sizeof(InD));

    queue<int> que;  // 记录入度为0
    for (int i = 0; i < N + M; ++i) {
        if (curInD[i] == 0) {
            que.push(i);
        }
    }

    int num = 0;
    while ( !que.empty()) {
        int cur = que.front();
        que.pop();
        ++num;

        for (int i = 0; i < tab[cur].size(); ++i) {
            int nex = tab[cur][i];

            if (curInD[nex] != 0) {
                --curInD[nex];
                if (curInD[nex] == 0) {
                    que.push(nex);
                }
            }
        }
    }

    if (num == N + M) {
        return false;
    }
    else {
        return true;
    }
}

void compute(int N, int M) {
    bool ini[MAXN] = {false};

    int curInD[MAXN + MAXM];
    memcpy(curInD, InD, sizeof(InD));

    queue<int> que;  // 记录入度为0
    for (int i = 0; i < N + M; ++i) {
        if (curInD[i] == 0) {
            que.push(i);
        }
    }

    while ( !que.empty()) {
        int cur = que.front();
        que.pop();

        for (int i = 0; i < tab[cur].size(); ++i) {
            int nex = tab[cur][i];

            if (curInD[nex] != 0) {
                --curInD[nex];

                // 器件未被初始化过, 没遇到过输入
                if (ini[nex - M] == false) {
                    output[nex] = output[cur];
                    ini[nex - M] = true;
                    if (type[nex - M] == "NOT") {
                        output[nex] = !output[nex];
                    }
                }
                // 遇见过输入
                else {
                    if (type[nex - M] == "AND" || type[nex - M] == "NAND") {
                        output[nex] = output[nex] & output[cur];
                    }
                    else if (type[nex - M] == "OR" || type[nex - M] == "NOR") {
                        output[nex] = output[nex] | output[cur];
                    }
                    else if (type[nex - M] == "XOR") {
                        output[nex] = output[nex] ^ output[cur];
                    }
                }

                if (curInD[nex] == 0) {
                    que.push(nex);
                    if (type[nex - M] == "NOR" || type[nex - M] == "NAND") {
                        output[nex] = !output[nex];
                    }
                }
            }
        }
    }
}

int main() {
    int Q;
    cin>>Q;

    for (int q = 0; q < Q; ++q) {
        int M, N;
        cin>>M>>N;

        fill(InD, InD + MAXM + MAXN, 0);  // 初始化入度  // 清理

        // 输入器件信息, 构建邻接表
        for (int n = 0; n < N; ++n) {
            cin>>type[n];
            int K;  // 每个器件的输入数
            cin>>K;

            InD[n + M] = K;  // 记录器件入度数
            for (int k = 0; k < K; ++k) {
                string t;
                cin>>t;

                int pre = atoi(t.substr(1).c_str()) - 1;  // -1, start from 0
                if (t[0] == 'O') {             // 器件编号 (-1+m)
                    pre += M;
                }
                tab[pre].emplace_back(n + M);  // 构建邻接表
            }
        }

        // S个输入
        int S;
        cin>>S;
        // S个输入的输入
        for (int s = 0; s < S; ++s) {
            input.emplace_back();
            for (int m = 0; m < M; ++m) {
                int cur;
                cin>>cur;
                input[s].emplace_back(cur);
            }
        }
        // S个输入对应要求输出的器件的编号
        for (int s = 0; s < S; ++s) {
            outputDev.emplace_back();
            int num;
            cin>>num;
            for (int n = 0; n < num; ++n) {
                int cur;
                cin>>cur;
                cur += (M - 1);
                outputDev[s].emplace_back(cur);
            }
        }

        // 成环
        if (topologicalSort(N, M)) {
            cout<<"LOOP"<<endl;
        }
        // 不成环
        else {
            for (int s = 0; s < S; ++s) {
                // 初始化
                fill(output, output + MAXN + MAXM, 0);  // 清理
                for (int i = 0; i < M; ++i) {
                    output[i] = input[s][i];
                }

                compute(N, M);

                // 输出
                for (int i = 0; i < outputDev[s].size(); ++i) {
                    cout<<output[outputDev[s][i]]<<" ";
                }
                cout<<endl;
            }
        }

        // 清理一下
        input.clear();
        outputDev.clear();
        for (int i = 0; i < MAXN + MAXM; i++) {
            tab[i].clear();
        }
        /*
        for (int i = 0; i < MAXN; ++i) {
            type[i] = "";
        }
        */
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值