社区讨论
拓扑排序+并查集,只有40分,求助各位巨佬,明天就考了
P9869[NOIP2023] 三值逻辑参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miim6gb1
- 此快照首次捕获于
- 2025/11/28 16:42 3 个月前
- 此快照最后确认于
- 2025/11/29 15:10 3 个月前
CPP
#include <bits/stdc++.h>
using namespace std;
int c, t, n, m, _i, _j, result;
char v;
//并查集查找和合并函数
int find(int *DSU, const int x) {
return x == DSU[x] ? x : DSU[x] = find(DSU, DSU[x]);
}
void merge(int *DSU, const int x, const int y) {
const int i = find(DSU, x), j = find(DSU, y);
if (i != j) DSU[i] = j;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> c >> t;
while (t--) {
result = 0;
cin >> n >> m;
int DSU[n + 1];
for (int i = 0; i <= n; ++i) DSU[i] = i;
int father[n + 1] = {}, indegree[n + 1] = {};
bool is_reversed[n + 1] = {}, is_visited[n + 1] = {};
char value_list[n + 1] = {};
queue<int> q;
while (m--) {
cin >> v;
if (v == '+') {
cin >> _i >> _j;
if (value_list[_j] != '\0') {
father[_i] = 0;
is_reversed[_i] = false;
value_list[_i] = value_list[_j];
} else {
father[_i] = _j;
is_reversed[_i] = false;
value_list[_i] = '\0';
}
} else if (v == '-') {
cin >> _i >> _j;
if (value_list[_j] != '\0') {
father[_i] = 0;
is_reversed[_i] = false;
if (value_list[_j] == 'T') value_list[_i] = 'F';
else if (value_list[_j] == 'F') value_list[_i] = 'T';
else value_list[_i] = 'U';
} else {
father[_i] = _j;
is_reversed[_i] = true;
value_list[_i] = '\0';
}
} else {
cin >> _i;
father[_i] = 0;
is_reversed[_i] = false;
value_list[_i] = v;
}
}
for (int i = 1; i <= n; ++i) {
if (father[i] == 0) continue;
merge(DSU, i, father[i]);
indegree[father[i]]++;
}
//拓扑排序去除非环边
for (int i = 1; i <= n; ++i) {
if (indegree[i] == 0 && father[i] != 0) {
q.push(i);
is_visited[i] = true;
}
}
while (!q.empty()) {
const int front = q.front();
q.pop();
indegree[father[front]]--;
if (father[front] != 0 && indegree[father[front]] == 0) q.push(father[front]);
}
for (int i = 1; i <= n; ++i) {
if (is_visited[i] || indegree[i] == 0) continue;
//遍历所有环
int reverse_cnt = 0;
bool is_started = false;
int j = i;
while (!is_started || j != i) {
if (!is_started) is_started = true;
reverse_cnt += is_reversed[j];
is_visited[j] = true;
j = father[j];
}
//如果环上反转次数为奇数,将与环连通的所有节点设为U
if (reverse_cnt % 2 != 0) value_list[find(DSU, i)] = 'U';
}
for (int i = 1; i <= n; ++i) {
if (value_list[find(DSU, i)] == 'U' || value_list[i] == 'U') result++;
}
cout << result << endl;
}
return 0;
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...