1. 题目详情
https://blog.csdn.net/weixin_45884316/article/details/108572358
2. 思路:
一句话:拓扑排序,在每次出队时计算出队的器件的输出。
此题复杂之处在于题目各种数据的存储方式,以本人的设置为例:
//相关数组大小
const int N = 510 , K = 5 , M = N * N / 2 , SM = 1e4;
//<char , int>二元组
typedef pair<char , int> PCI;
//器件结构体数组
struct func
{
char fun[K]; //器件功能
PCI port[K];//端口,char表示I/O,int表示I/O的编号
int out; //本器件的输出
int p_num; //端口数目
}funcs[N];
int input[SM][N * K];//多轮输入
int q[N]; //询问
int h[N] , e[M] , ne[M] , idx;//邻接表
int d[N]; //结点(器件)入度
int bkd[N]; //入度数组备份
int in_num , func_num; //输入、器件总数目
3. 代码实现
#include <iostream>
#include <cstring>
#include <queue>
#include <stdlib.h>
#define x first
#define y second
using namespace std;
const int N = 510 , K = 5 , M = N * N / 2 , SM = 1e4;
typedef pair<char , int> PCI;
struct func
{
char fun[K];
PCI port[K];
int out;
int p_num;
}funcs[N];
int input[SM][N * K];
int q[N];
int h[N] , e[M] , ne[M] , idx;
int d[N];
int bkd[N];
int in_num , func_num;
void add(int a , int b)
{
e[idx] = b , ne[idx] = h[a] , h[a] = idx++;
}
bool topsort(int s)
{
queue<int> qu;
int a[N];
int cnt = 0;
for(int i = 1; i <= func_num; ++i)
if(!d[i]) qu.push(i);
while(qu.size())
{
int t = qu.front();
a[++cnt] = t;
// printf("%d\n" , t);
qu.pop();
int & out = funcs[t].out;
int & pnum = funcs[t].p_num;
if(funcs[t].port[1].x == 'O') out = funcs[ funcs[t].port[1].y ].out;
else out = input[s][funcs[t].port[1].y];
if(!strcmp(funcs[t].fun , "AND"))
{
for(int i = 2; i <= pnum; ++i)
{
if(funcs[t].port[i].x == 'O') out &= funcs[ funcs[t].port[i].y ].out;
else out &= input[s][funcs[t].port[i].y];
}
}
else if(!strcmp(funcs[t].fun , "OR"))
{
for(int i = 2; i <= funcs[t].p_num; ++i)
{
if(funcs[t].port[i].x == 'O') out |= funcs[ funcs[t].port[i].y ].out;
else out |= input[s][funcs[t].port[i].y];
}
}
else if (!strcmp(funcs[t].fun , "XOR"))
{
for(int i = 2; i <= funcs[t].p_num; ++i)
{
if(funcs[t].port[i].x == 'O') out ^= funcs[ funcs[t].port[i].y ].out;
else out ^= input[s][funcs[t].port[i].y];
}
}
else if (!strcmp(funcs[t].fun , "NAND"))
{
for(int i = 2; i <= funcs[t].p_num; ++i)
{
if(funcs[t].port[i].x == 'O') out &= funcs[ funcs[t].port[i].y ].out;
else out &= input[s][funcs[t].port[i].y];
}
out ^= 1;
}
else if (!strcmp(funcs[t].fun , "NOR"))
{
for(int i = 2; i <= funcs[t].p_num; ++i)
{
if(funcs[t].port[i].x == 'O') out |= funcs[ funcs[t].port[i].y ].out;
else out |= input[s][funcs[t].port[i].y];
}
out ^= 1;
}
else out ^= 1;
for(int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if(--d[j] == 0)
{
qu.push(j);
}
}
}
if(cnt == func_num && cnt) return true;
else return false;
// for(int i = 1; i <= func_num; ++i)
// if(d[i]) return false;
// return true;
}
int main()
{
// freopen("in.txt" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
int Q;
scanf("%d" , &Q);
while(Q--)
{
scanf("%d%d" , &in_num, &func_num);
// getchar();
idx = 0;
memset(h , -1 , sizeof(h));
memset(e , 0 , sizeof(e));
memset(ne , 0 , sizeof(ne));
memset(d , 0 , sizeof(d));
memset(funcs , 0 , sizeof(funcs));
memset(input , 0 , sizeof(input));
for(int i = 1; i <= func_num; ++i)
{
scanf("%s" , funcs[i].fun);
// printf("%s\n" , funcs[i].fun);
scanf("%d" , &funcs[i].p_num);
// getchar();
for(int j = 1; j <= funcs[i].p_num; ++j)
{
char tp[10];
scanf("%s" , tp);
int t = atoi(tp + 1);
funcs[i].port[j].x = tp[0];
funcs[i].port[j].y = t;
if(tp[0] == 'O')
{
add(t , i);
++d[i];
}
// printf("%c%d\n" , funcs[i].port[j].x ,funcs[i].port[j].y);
}
}
memcpy(bkd , d , sizeof(d));
// for(int i = 1; i <= func_num; ++i) printf("%d ", d[i]);
int S;
scanf("%d" , &S);
for(int i = 1; i <= S; ++i)
{
for(int j = 1; j <= in_num; ++j)
{
scanf("%d" , &input[i][j]);
// printf("%d\n" , input[i][j]);
}
}
bool has_loop = false;
//solution
for(int i = 1; i <= S; ++i)
{
memset(q , 0 , sizeof(q));
int s;
scanf("%d" , &s);
for(int j = 1; j <= s; ++j)
scanf("%d" , &q[j]);
if(!topsort(i))
{
has_loop = true;
//break;
}
else
{
for(int j = 1; j < s; ++j)
printf("%d ", funcs[q[j]].out);
printf("%d", funcs[q[s]].out);
puts("");
}
// for(int j = 1; j <= func_num; ++j)
// printf("%d " , funcs[j].out);
memcpy(d , bkd , sizeof(d));
for(int i = 1; i <= func_num; ++i) funcs[i].out = 0;
}
if(has_loop) puts("LOOP");
//reset
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
特别鸣谢
https://blog.csdn.net/u011902923/article/details/108890765?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242
这篇博客的大佬指出了输入读取不完全的问题,特此表达感谢!