题意:这道题大体就是给你一个组合电路,有输入信号和电器元件,他给你一些值然后让你输出询问的电器元件计算的值。
首先是输入:
第一行是q代表查询的次数,然后是m,n,分别是输入信号的数目和电器元件的数目。之后n行是电器元件作用(像AND,XOR等),然后是输入的信号的数目,后面是电器元件的符号(Ox)或者输入信号的符号(Ix)。然后是s代表运行的次数,之后是s行代表每次运行所有的输入信号的值(只有0和1两种)。之后s行每行第一个是要输出的电器元件的数目,之后是电器元件的序号(数字)。
然后是输出:
输出就是对最后s行每行查询的电器元件,输出他计算的值。(当然你还要判断是否有环路)
解题思路:
其实仔细一想这就是个拓扑排序。首先如果没有某个电器元件的输入量全是输入信号的,那么就一定存在环路,直接输出loop就行了。如果有的话,就可以设置电器元件的输入的其他电器元件的数目,存放在in数组里面(全是输入信号的话值为0,这个就是拓扑排序的起始点)。然后用队列直接实现拓扑排序就行了。
而在这里我用的结构体记录的电器元件和输入信号的信息。
上代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
int in[100000]={0},q1,m,n,s;
vector<int> h[50005],g[50005];//这个是每次运行的所有信号量的值和你要输出的电器元件的信号
int in1[100000]={0},out1[100000]={0};//in1代表每次运行的(in代表的东西上面说了),out1就是我记录每个电器元件的计算的值
int flag;//flag=0代表有环路
struct node{
string zt;
int num;
vector<int> u,v;
}e[100000];//结构体,zt是状态(如AND),num是计算的值,u是该电器元件的输入的信号或元件的序号,v是该元件是,,,的输入信号
int sol(string tt){//这个函数是将Ix和Ox转化成序号
if(tt[0]=='I'){
int tot=0;
for(i/nt i=1;i<tt.size();i++){
tot*=10;
tot+=int(tt[i]-'0');
}
return tot;
}else if(tt[0]=='O'){
int tot=0;
for(int i=1;i<tt.size();i++){
tot*=10;
tot+=int(tt[i]-'0');
}
tot+=m;
return tot;
}
}//在这里前m个是输入信号量,电器元件序号加m
void solve(int u){//这个是根据状态求计算的值
if(e[u].zt=="NOT"){
e[u].num=(!e[e[u].u[0]].num);
}
if(e[u].zt=="AND"){
e[u].num=1;
for(int i=0;i<e[u].u.size();i++)
{
e[u].num=(e[u].num&e[e[u].u[i]].num);
}
}
if(e[u].zt=="OR"){
e[u].num=0;
for(int i=0;i<e[u].u.size();i++)
{
e[u].num=(e[u].num|e[e[u].u[i]].num);
}
}
if(e[u].zt=="XOR"){
e[u].num=0;
for(int i=0;i<e[u].u.size();i++)
{
e[u].num=(e[u].num^e[e[u].u[i]].num);
}
}
if(e[u].zt=="NAND"){
e[u].num=1;
for(int i=0;i<e[u].u.size();i++)
{
e[u].num=(e[u].num&e[e[u].u[i]].num);
}
e[u].num=(!e[u].num);
}
if(e[u].zt=="NOR"){
e[u].num=0;
for(int i=0;i<e[u].u.size();i++)
{
e[u].num=(e[u].num|e[e[u].u[i]].num);
}
e[u].num=(!e[u].num);
}
}
void dfs(){//拓扑排序
queue<int> q;
for(int i=1;i<=m+n;i++){
in1[i]=in[i];
}
for(int i=m+1;i<=m+n;i++){//这个是我上面说的判断环路
if(in1[i]==0){
q.push(i);
flag=1;
}
}
if(!flag)return;
int hh=n;
while(!q.empty()){
int u=q.front();
q.pop();
solve(u);
out1[u-m]=e[u].num;
hh--;
for(int i=0;i<e[u].v.size();i++){
int cnt=e[u].v[i];
in1[cnt]--;
if(in1[cnt]==0){
q.push(e[u].v[i]);
}
}
}
if(hh!=0){//如果依然存在电器元件没有更新,说明存在环路
flag=0;
}
}
int main()
{
cin>>q1;
while(q1--){
flag=0;
cin>>m>>n;
for(int i=0;i<10000;i++){//这个是初始化
h[i].clear();
g[i].clear();
}
for(int i=1;i<=m+n;i++){
in[i]=0;
}
for(int i=1;i<=m;i++){
e[i].zt="0";
e[i].num=-1;
e[i].u.clear();
e[i].v.clear();
}
for(int i=m+1;i<=m+n;i++){//对于每个信号或元件进行结构体构建
e[i].num=0;
e[i].u.clear();
e[i].v.clear();
string p;
cin>>p;
e[i].zt=p;
int a1;
cin>>a1;
for(int j=0;j<a1;j++){
string tt;
cin>>tt;
int num=sol(tt);
e[i].u.push_back(num);
if(num>m){
in[i]++;
e[num].v.push_back(i);
}
}
}
cin>>s;
int w;
for(int i=0;i<s;i++){//存储每次运行信号的值
for(int j=0;j<m;j++){
cin>>w;
h[i].push_back(w);
}
}
for(int i=0;i<s;i++){//要查询的信号
int ww;
cin>>ww;
for(int j=0;j<ww;j++){
cin>>w;
g[i].push_back(w);
}
}
for(int i=0;i<s;i++){
memset(out1,0,sizeof(out1));
memset(in1,0,sizeof(in1));
for(int j=1;j<=m;j++){
e[j].num=h[i][j-1];
}
dfs();
if(!flag){//判断是否有环
cout<<"LOOP"<<endl;
break;
}
for(int j=0;j<g[i].size();j++){
cout<<out1[g[i][j]]<<" ";//输出
}
cout<<endl;
}
}
}