在这里插入图片描述

本题并不难,主要在于将电路连接图抽象为有向图,然后进行简单拓扑排序即可,下文给出代码在已在几个点给出注释

/*
 * @Author: csc
 * @Date: 2020-12-14 17:29:08
 * @LastEditTime: 2020-12-19 19:10:17
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \code\csp\2009_3.cpp
 */
#include <bits/stdc++.h>
const int N = 1e4 + 100;
const int M = 1000;

using namespace std;

int m, n, s, k;
vector<int> tin[N], tout[N];// 存输入输出数据
typedef struct Node
{
    int v;
    Node(int vv) : v(vv) {}
} node;
vector<node> ad[M];//邻接表存储
int in[M], w[M];// in 存入度   w存出度
bool vis[M];//  标志结点是否遍历到  在cal函数中使用到
map<int, string> device;//采用map函数映射每个结点对应的器件
void init()
{
    fill(vis, vis + M, false);
    memset(in, 0, sizeof(in));
    for (int i = 0; i < N; ++i)
    {
        tin[i].clear();
        tout[i].clear();
    }
    for (int i = 0; i < M; ++i)
    {
        ad[i].clear();
    }
    device.clear();
}
void _init()
{
    fill(vis, vis + M, false);
    memset(w, 0, sizeof(w));
}
bool tp()//进行一次拓扑排序,验证存不存在环,不存在则返回false
{
    int cnt = 0;
    queue<int> q;
    int f[M] = {0};
    memcpy(f, in, (m + n) * sizeof(int));
    //复制入度数组,方便后序计算
    for (int i = 0; i < n + m; ++i)
        if (!f[i])
            q.push(i);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = 0; i < ad[u].size(); ++i)
        {
            int v = ad[u][i].v;
            f[v]--;
            if (!f[v])
                q.push(v);
        }
        cnt++;//计算遍历到的结点数,若不存在环则每个结点
        //应刚好遍历一次。反之,若存在环则不可能遍历到每个结点
    }
    return (cnt == n + m) ? true : false;
}
void cal()//依托拓扑排序进行计算
{
    queue<int> q;
    int f[M] = {0};
    memcpy(f, in, (m + n) * sizeof(int));
    for (int i = 0; i < n + m; ++i)
        if (!f[i])
            q.push(i);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = 0; i < ad[u].size(); ++i)
        {
            int v = ad[u][i].v;
            f[v]--;
            if (!vis[v])
            {
                w[v] = w[u];//每个逻辑器(除了非)都会有两个输入
                //第一个输入不做处理,只进行赋值
                vis[v] = true;
            }
            else
            {
                if (device[v] == "AND" || device[v] == "NAND")
                    w[v] &= w[u];
                else if (device[v] == "OR" || device[v] == "NOR")
                    w[v] |= w[u];
                else if (device[v] == "XOR")
                    w[v] ^= w[u];
            }
            if (!f[v])
            {
                if (device[v][0] == 'N')
                    w[v] = (!w[v]);//与非和或非要取一次非;而前面对非
                    //进行赋值时未进行取非,在这里对三者统一取非
                q.push(v);
            }
        }
    }
}
int getnum(string s)
{
    int res = 0;
    for (int i = 1; i < s.length(); ++i)
        res = res * 10 + (s[i] - '0');
    return (res - 1);
}

int main()
{
    int _ = 1;
    cin >> _;
    while (_--)
    {
        init();
        cin >> m >> n;
        for (int i = m; i < n + m; ++i)
        {
            string F;
            cin >> F;
            device[i] = F;
            cin >> k;
            for (int j = 0; j < k; ++j)
            {
                string I;
                cin >> I;
                int st = getnum(I);
                if (I[0] != 'I')
                    st += m;
                ad[st].push_back(node(i));
                in[i]++;
            }
        }
        cin >> s;
        for (int i = 0; i < s; ++i)
        {
            for (int j = 0; j < m; ++j)
            {
                int x;
                cin >> x;
                tin[i].push_back(x);
            }
        }
        for (int i = 0; i < s; ++i)
        {
            int S;
            cin >> S;
            for (int j = 0; j < S; ++j)
            {
                int x;
                cin >> x;
                tout[i].push_back(x + m - 1);
            }
        }

        if (!tp())
            cout << "LOOP" << endl;
        else
        {
            for (int i = 0; i < s; ++i)
            {
                _init();
                for (int j = 0; j < tin[i].size(); ++j)
                    w[j] = tin[i][j];
                cal();
                for (int j = 0; j < tout[i].size(); ++j)
                {
                    if (j != 0)
                        cout << " ";
                    cout << w[tout[i][j]];
                }
                cout << endl;
            }
        }
    }

    return 0;
}
Logo

电影级数字人,免显卡端渲染SDK,十行代码即可调用,工业级demo免费开源下载!

更多推荐