LCT,或者并查集水过。
首先并查集这道题不能路径压缩,因为路径压缩是为了用牺牲一些信息的方法来加快速度,可是这道题我们需要这个信息,所以不能路径压缩。
剩下的操作就只剩下了暴力并查集,而每次查询前都要使u所在的树换根,使u换为该树的根,可以方便查询。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define N 4011
using namespace std;
int n, m, fa[401100];
inline int query(int u, int v)
{
while (v && u != v)
{
v = fa[v];
if (v == u)
return 1;
}
if (u == 0) return 1;
if (v == u) return 1;
return 0;
}
inline void connect(int u, int v)
{
fa[u] = v;
}
inline void destroy(int u, int v)
{
fa[v] = 0;
}
signed main()
{
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= m; i++)
{
string s; int u, v, temp = 0, u1, ha;
cin >> s;
scanf("%lld%lld", &u, &v);
u1 = u;
while (u1)//换根操作,使u为u所在的树的根
{
ha = fa[u1];
fa[u1] = temp; temp = u1; u1 = ha;
}
if (s == "Connect")
connect(u, v);
if (s == "Destroy")
destroy(u, v);
if (s == "Query")
{
if (query(u, v))
printf("Yes
");
else
printf("No
");
}
}
return 0;
}