根据每个数收那个位置初值影响建边,能证明只存在自环,但在洛谷上的 #7 出现了环
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define lb lower_bound
#define re register
#define sz(x) (int(x.size()))
#define all(x) x.begin(), x.end()
using namespace std;
int rd() {
int w = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {w = (w << 3) + (w << 1) + ch - 48; ch = getchar();}
return f * w;
}
int main() {
int c, t;
scanf("%d%d", &c, &t);
while (t -- ) {
int n = rd(), m = rd(), ans = 0;
vector<int> fu(n + 10), p(n + 10), vis(n + 10);
for (int i = 1; i <= n; i ++ ) fu[i] = 0, p[i] = i;
for (int i = 1; i <= m; i ++ ) {
char c;
cin >> c;
if (c == 'T') {
int x = rd();
fu[x] = 0;
p[x] = n + 1;
} else if (c == 'F') {
int x = rd();
fu[x] = 0;
p[x] = n + 2;
} else if (c == 'U') {
int x = rd();
fu[x] = 0;
p[x] = n + 3;
} else if (c == '+') {
int i = rd(), j = rd();
fu[i] = fu[j], p[i] = p[j];
} else if (c == '-') {
int i = rd(), j = rd();
fu[i] = fu[j] ^ 1, p[i] = p[j];
}
}
//vis 值 1表示 T 或 F,2表示在当前栈内,3表示为 U
vis[n + 1] = vis[n + 2] = 1;
vis[n + 3] = 3;
for (int i = 1; i <= n; i ++ )
if (p[i] == i && fu[i] == 1)
vis[i] = 3, ans ++ ;
else if (p[i] == i)
vis[i] = 1;
for (int i = 1; i <= n; i ++ ) {
if (vis[i]) continue;
int j = i;
int cnt = 1;
vector<int> g;
g.pb(j);
vis[j] = 2;
while (vis[p[j]] == 0) {
j = p[j];
vis[j] = 2;
g.pb(j);
cnt ++ ;
}
if (vis[p[j]] == 1) {
for (int vv : g) vis[vv] = 1;
} else if (vis[p[j]] == 3) {
for (int vv : g) vis[vv] = 3;
ans += cnt;
} else {
//int *ipx = 0; *ipx = 0;
//存在环
for (int vv : g) vis[vv] = 1;
}
}
printf("%d\n", ans);
}
return 0;
}