【CSP】202009-3点亮数字人生(拓扑排序)
本题并不难,主要在于将电路连接图抽象为有向图,然后进行简单拓扑排序即可,下文给出代码在已在几个点给出注释/** @Author: csc* @Date: 2020-12-14 17:29:08* @LastEditTime: 2020-12-19 19:10:17* @LastEditors: Please set LastEditors* @Description: In User Settin
·

本题并不难,主要在于将电路连接图抽象为有向图,然后进行简单拓扑排序即可,下文给出代码在已在几个点给出注释
/*
* @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;
}
更多推荐


所有评论(0)