思路:
抽象成图的问题 定义邻接表数据结构并初始化
typedef struct Node{
int v;//边的终点
Node(int _v):v(_v){}//初始化列表
}node;
std::vector<node> Adj[MAXV];//邻接表
审题:
1.因为题目中包含Q个问题,所以存放数据的结构每次循环开始的时候都要进行初始化。
2.输入分为两部分,顺序读入。
3.第一部分:
(1)第一行M、N表示整个电路的输入和器件的数量,N最大是500,
(2)接下来N行(从m+1到m+n),FUNC表示逻辑功能,存放在string[510]中,然后输入k,再循环k次输入,并根据此来构造图(处理输入的字符串,然后得到该器件的编号startPoint,然后令Adj[startPoint]指向num,并计算入度为广搜作准备)。
4.第二部分:
(1)第一行S表示电路运行的次数,S最大是10000.
(2)接下来S行,每行输入m个0或1,并存放在testInput[10010]中。
(3)接下来S行,根据输出器件的个数循环,并将输出器件的编号存放到testOutput[10010]中
5.拓扑循环来判断图里是否有环。
6.计算输出结果:
这里需要注意的是,因为要计算S次,所以点权值w[510]和是否访问过该点的数组visited[510]在每次计算前都要初始化,而且计算时要用一个临时数组来存放入度值。
7.题目中涉及到的字符串和数组操作:
memset(inDegree, 0, sizeof(inDegree));
std::fill(initV, initV + MAXV, false);
for(std::vector<node>::iterator j = Adj[i].begin();j != Adj[i].end();){
j = Adj[i].erase(j);
}
for(int i = 0;i < MAXV;i++){
type[i].clear();
}
memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数
8.代码:
#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<string.h>
#include<algorithm>
//#include <bits/stdc++.h>
//using namespace std;
const int MAXV = 510;
typedef struct Node{
int v;//边的终点
Node(int _v):v(_v){}//初始化列表
}node;
std::vector<node> Adj[MAXV];//邻接表
int w[MAXV];//边权重
//bool inq[MAXV] = {false};//是否访问过
bool initV[MAXV] = {false};//是否初始化过边
int inDegree[MAXV] = {0};//入度
//int outDegree[MAXV] = {0};//出度(未使用)
std::string type[MAXV]; //器件类型
std::vector<int> testInput[10010];//测试输入
std::vector<int> testOutput[10010];//测试输出
//拓扑排序,判断环
bool TopologicalSort(int n, int m){
int num = 0;
std::queue<int> q;
int tempInDegree[MAXV];//临时存储入度
memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数
// std::copy(std::begin(inDegree), std::end(inDegree), std::begin(tempInDegree));
for(int i = 0;i < n + m;i++){//将所有入度为0的顶点入队
if(tempInDegree[i] == 0){
q.push(i);
}
}
while(!q.empty()){
int u = q.front();
q.pop();
//邻接表
for(int i = 0;i < Adj[u].size();i++){
int v = Adj[u][i].v;
tempInDegree[v]--;
if(tempInDegree[v] == 0){
q.push(v);
}
}
num++;
}
if(num == n + m) return true;
else return false;
}
//计算值
void calculateValue(int n, int m){
std::queue<int> q;
int tempInDegree[MAXV];//临时存储入度
memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数
for(int i = 0;i < n + m;i++){//将所有入度为0的顶点入队
if(tempInDegree[i] == 0){
q.push(i);
}
}
while(!q.empty()){
int u = q.front();//起始点
q.pop();
//邻接表
for(int i = 0;i < Adj[u].size();i++){
int v = Adj[u][i].v;
tempInDegree[v]--;
if(initV[v] == false){//之前没有被访问过
w[v] = w[u];//赋予初始值
if(type[v] == "NOT"){//最多或者最少都只有一个输入
w[v] = (!w[v]);
}
initV[v] = true;
}else{
if(type[v] == "AND" || type[v] == "NAND"){
w[v] &= w[u];
}else if(type[v] == "OR" || type[v] == "NOR"){
w[v] |= w[u];
}else if(type[v] == "XOR"){
w[v] ^= w[u];
}
}
if(tempInDegree[v] == 0){
if(type[v] == "NAND" || type[v] == "NOR"){
w[v] = (!w[v]);
}
q.push(v);
}
}
}
}
int main(){
int q, m, n;
scanf("%d", &q);
while(q--){//问题个数
//初始化
for(int i = 0;i < MAXV;i++){
for(std::vector<node>::iterator j = Adj[i].begin();j != Adj[i].end();){
j = Adj[i].erase(j);
}
}
//std::fill(G[0], G[0] + MAXV*MAXV, 0);
memset(inDegree, 0, sizeof(inDegree));
//memset(outDegree, 0, sizeof(outDegree));
// std::fill(inq, inq + MAXV, false);
std::fill(initV, initV + MAXV, false);
for(int i = 0;i < MAXV;i++){
type[i].clear();
}
for(int i = 0;i < 10010;i++){
for(std::vector<int>::iterator j = testInput[i].begin();j != testInput[i].end();){
j = testInput[i].erase(j);
}
}
for(int i = 0;i < 10010;i++){
for(std::vector<int>::iterator j = testOutput[i].begin();j != testOutput[i].end();){
j = testOutput[i].erase(j);
}
}
scanf("%d%d", &m, &n);//输入个数,器件个数
for(int num = m;num < n + m;num++){
std::string FUNC;//器件描述
int k;
std::cin>>FUNC;
type[num] = FUNC;
scanf("%d", &k);
for(int i = 0;i < k;i++){
std::string L;
std::cin>>L;
int startPoint = std::atoi(L.substr(1, L.length() - 1).c_str()) - 1;//计算起始点编号
if(L[0] != 'I'){//如果是输出点,则加上输入点的偏移
startPoint += m;
}
Adj[startPoint].push_back(node(num));//构造图
//G[startPoint][num] = 1;
// outDegree[startPoint]++;//计算出度
inDegree[num]++;//计算入度
}
}
int s;//运算次数
scanf("%d", &s);
for(int i = 0;i < s;i++){//输入数据
for(int j = 0;j < m;j++){
int input;
scanf("%d", &input);
testInput[i].push_back(input);
}
}
for(int i = 0;i < s;i++){//输出数据
int OutNum;
scanf("%d", &OutNum);
while(OutNum--){
int output;
scanf("%d", &output);
output = output + m - 1;
testOutput[i].push_back(output);
}
}
if(TopologicalSort(n, m) == false){//有环
printf("LOOP\n");
}else{//无环
for(int i = 0;i < s;i++){
memset(w, 0, sizeof(w));
//std::fill(inq, inq + MAXV, false);
std::fill(initV, initV + MAXV, false);
for(int j = 0;j < testInput[i].size();j++){//给初始输入点赋值
w[j] = testInput[i][j];
}
//计算点权
calculateValue(n, m);
for(int j = 0; j < testOutput[i].size();j++){
if(j != 0) printf(" ");
printf("%d", w[testOutput[i][j]]);
}
printf("\n");
}
}
}//q
return 0;
}