• CSP202009-3 点亮数字人生(拓扑排序)


    不难的大模拟,思路就是拓扑排序或者dfs判环,需要注意的是当一个点入度为0,说明邻接到它的点的值已经计算出来了,这时候就可以计算这个点的值了。

    坑点:当为loop的时候不能break,而是应该设置标记,然后把剩下的数据都读入(不作处理),最后输出一个loop。在这里卡了两个多小时。。

    #include <bits/stdc++.h>
    using namespace std;
    int Q, M, N, S;
    struct node {
    	int id, func, k;
    	vector<int> I, O, out;
    } e[100005];
    int deg[100005], orideg[100005];
    int tran(string s) {
    	int ans = 0;
    	for(int i = 0; i < s.size(); i++) {
    		ans *= 10;
    		ans += (s[i] - '0');
    	}
    	return ans;
    }
    int result[100005];
    queue<int> q;
    void calc(int id) {
    	if(!e[id].k) return;//k为0是输入 result已经有值了 直接返回
    	if(e[id].func == 1) {
    		if(e[id].I.size()) {
    			result[id] = !result[e[id].I[0]];
    		} else {
    			result[id] = !result[e[id].O[0]];
    		}
    	} else if(e[id].func == 2) {
    		int ans = 1;
    		for(auto x : e[id].I) ans = ans & result[x];
    		for(auto x : e[id].O) ans = ans & result[x];
    		result[id] = ans;
    	} else if(e[id].func == 3) {
    		int ans = 0;
    		for(auto x : e[id].I) ans = ans | result[x];
    		for(auto x : e[id].O) ans = ans | result[x];
    		result[id] = ans;
    	} else if(e[id].func == 4) {
    		int ans = -1;
    		for(auto x : e[id].I) {
    			if(ans == -1) ans = result[x];
    			else ans = ans ^ result[x];
    		}
    		for(auto x : e[id].O) {
    			if(ans == -1) ans = result[x];
    			else ans = ans ^ result[x];
    		}
    		result[id] = ans;
    	} else if(e[id].func == 5) {
    		int ans = 1;
    		for(auto x : e[id].I) ans = ans & result[x];
    		for(auto x : e[id].O) ans = ans & result[x];
    		result[id] = !ans;
    	} else {
    		int ans = 0;
    		for(auto x : e[id].I) ans = ans | result[x];
    		for(auto x : e[id].O) ans = ans | result[x];
    		result[id] = !ans;
    	}
    }
    int main() {
    	cin >> Q;
    	while(Q--) {
    		cin >> M >> N;
    		bool loop = 0;
    		memset(orideg, 0, sizeof(orideg));
    		memset(deg, 0, sizeof(deg));
    		memset(result, 0, sizeof(result));
    		while(q.size()) q.pop();
    		for(int i = 0; i <= N + M + 5; i++) e[i].k = 0, e[i].id = i, e[i].I.clear(), e[i].O.clear(), e[i].out.clear();
    		for(int i = 1; i <= N; i++) {
    			string FUNC;
    			int k;
    			cin >> FUNC;
    			cin >> k;
    			e[i].k = k;
    			if(FUNC == "NOT") e[i].func = 1;
    			else if(FUNC == "AND") e[i].func = 2;
    			else if(FUNC == "OR") e[i].func = 3;
    			else if(FUNC == "XOR") e[i].func = 4;
    			else if(FUNC == "NAND") e[i].func = 5;
    			else e[i].func = 6;
    			for(int j = 1; j <= k; j++) {
    				string tmp;
    				cin >> tmp;
    				int id = tran(tmp.substr(1));
    				if(tmp[0] == 'I') {
    					e[i].I.push_back(N + id);
    					e[N + id].out.push_back(i);
    					orideg[i]++;
    				} else {
    					e[i].O.push_back(id);
    					e[id].out.push_back(i);
    					orideg[i]++;
    				}
    			}
    		}
    		cin >> S;
    		vector<vector<int> > v(S);
    		for(int i = 1; i <= S; i++) {
    			for(int j = 1; j <= M; j++) {
    				int tmp;
    				cin >> tmp;
    				v[i - 1].push_back(tmp);
    			}
    		}
    		//cout << M << endl;
    		for(int i = 1; i <= S; i++) {
    			int s;
    			cin >> s;
    			for(int j = 1; j <= N + M; j++) {
    				deg[j] = orideg[j];
    				result[i] = 0;
    			}
    			while(q.size()) q.pop();
    			for(int j = 0; j < v[i - 1].size(); j++) {
    				result[N + j + 1] = v[i - 1][j];
    				q.push(j + 1 + N);//M个输入对应的节点入队
    			}
    			bool vis[5005];
    			for(int j = 1; j <= N + M; j++) vis[j] = 0;
    			int cnt = 0;
    			while(q.size()) {
    				if(loop) break;
    				int now = q.front(); q.pop();
    				calc(now);//计算它的result
    				for(auto x : e[now].out) {
    					deg[x]--;
    					if(deg[x] == 0 && (!vis[x])) {
    						q.push(x);
    						vis[x] = 1;
    						cnt++;
    					}
    				}
    			}
    			if(cnt != N) {
    				loop = 1;
    				for(int j = 1; j <= s; j++) {
    					int useless;
    					cin >> useless;
    				}
    			} else {
    				for(int j = 1; j <= s; j++) {
    					int query;
    					cin >> query;
    					cout << result[query] << " ";
    				}
    				cout << endl;
    			}
    		}
    		if(loop) puts("LOOP");
    	}
    	return 0;
    }
    
  • 相关阅读:
    c# 不常用逻辑运算符
    c# 简单日志记录类 log

    最短路径
    A+B
    floyd 算法
    Kruskal 算法
    快排
    顺序表的逆排
    顺序表中多余元素的删除
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15257032.html
Copyright © 2020-2023  润新知