并查集
ll f[maxn],num[maxn],dis[maxn];
//num[i]所在连通块的数量,dis[i]为i的深度
ll fd(ll x)
{
if(f[x]==x) return x;
ll k=f[x];
f[x]=fd(f[x]);
dis[x]+=dis[k];
num[x]=num[f[x]];
return f[x];
}
void fd(ll x,ll y)
{
ll fx=fd(x),fy=fd(y);
if(fx==fy) return;
f[fy]=fx;
dis[fy]=dis[fx]+num[fx];
num[fx]+=num[fy];
num[fy]=num[fx];
}
int main()
{
// DEBUG;
for(ll i=1;i<=1e5;i++)
{
f[i]=i;
num[i]=1;
}
}
求集合元素数量最大值
ll fd(ll x)//查找祖先
{
if(f[x]==x) return x;
else return f[x]=fd(f[x]);
}
void hb(ll x,ll y)//合并
{
ll fx=fd(x),fy=fd(y);
if(fx==fy)return;
num[fx]+=num[fy];
f[fy]=fx;
ans=max(ans,num[fx]);
}
int main()
{
for (ll i = 0; i < maxn; i++)
{
f[i] = i;
}
for (ll i = 0; i < maxn; i++)
num[i] = 1;//初始化
}
可撤销并查集
struct DSU
{
ll fa[MAXN];
ll sz[MAXN];
vector<pair<ll &, ll> > his_sz;
vector<pair<ll &, ll> > his_fa;
void init(ll n)
{
for (ll i = 1; i <= n; i++)
fa[i] = i, sz[i] = 1;
}
ll find(ll x)
{
while (x != fa[x])
x = fa[x];
return x;
}
bool same(ll u, ll v)
{
return find(u) == find(v);
}
void merge(ll u, ll v)
{
ll x = find(u);
ll y = find(v);
if (x == y)
return;
if (sz[x] < sz[y])
std::swap(x, y);
his_sz.push_back({sz[x], sz[x]});
sz[x] = sz[x] + sz[y];
his_fa.push_back({fa[y], fa[y]});
fa[y] = x;
}
ll histroy()
{
return his_fa.size();
}
void roll(ll h)
{
while (his_fa.size() > h)
{
his_fa.back().first = his_fa.back().second;
his_fa.pop_back();
his_sz.back().first = his_sz.back().second;
his_sz.pop_back();
}
}
} dsu;
最小生成树–Kruskal算法
ll fd(ll x)
{
if(f[x]==x) return x;
else return f[x]=fd(f[x]);
}
void hb(ll x,ll y)
{
ll fx=fd(x),fy=fd(y);
if(fx==fy) return;
f[fy]=fx;
}
struct Edge
{
ll u, v, len;
bool operator<(Edge other) const
{
return len < other.len;
}
} edges[maxn * maxn];
ll Kruskal()
{
sort(edges+1, edges + tot+1);
ll ans = 0, cnt = 0;
for (ll i = 1; i <= tot; i++)
{
ll fx = fd(edges[i].u), fy = fd(edges[i].v);
if (fx == fy)
continue;
else
{
ans += edges[i].len;
cnt++;
}
hb(fx, fy);
if (cnt == n - 1)
break;
}
if (cnt < n - 1)
return -1;
else
return ans;
}
int main()
{
for (ll i = 0; i < maxn; i++)
{
f[i] = i;
}
}