CSP202009-3 点亮数字人生(拓扑排序)
Posted 脂环
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于CSP202009-3 点亮数字人生(拓扑排序)的主要内容,如果未能解决你的问题,请参考以下文章
[CSP-S模拟测试]:Permutation(线段树+拓扑排序+贪心)
2017 Multi-University Training Contest - Team 9 1005&&HDU 6165 FFF at Valentine强联通缩点+拓扑排序((代