首页 > 代码库 > bzoj4668

bzoj4668

并查集+最小生成树

首先我们发现这题可以lct维护最小生成树,但是发现如果生成树在之后是不会修改的,那么就想到了并查集,然后就不知道怎么做了。。。

其实当我们连接两个连通块的时候,两个连通块只能通过这一条边联通,所以这条边的两个端点是谁并不重要,因为两个连通块之间的通道最小值不会受到位置的影响。那么我们就可以利用并查集进行按秩合并,使树高只有logn,然后每次查询就是暴力lca查找路径最值

技术分享
#include<bits/stdc++.h>
using namespace std;
int n, m, ans;
int fa[500010], d[500010];
int find(int x)
{
    if(x == fa[x]) return x;
    int a = find(fa[x]);
    d[a] = min(d[a], d[x]);
    return fa[x] = a;
}
void connect(int u, int v)
{
    int a = find(u), b = find(v);
    if(a == b) return;
    d[a] = min(d[a], d[b]);
    fa[b] = a;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) fa[i] = i;
    for(int i = 1; i <= m; ++i)
    {
        int opt, u, v;
        scanf("%d%d%d", &opt, &u, &v);
        u ^= ans;
        v ^= ans;
        if(opt == 0) connect(u, v);
        if(opt == 1)
        {
            int a = find(u), b = find(v);
            if(a != b) 
            {
                ans = 0;
                puts("0");
            }
            else printf("%d\n", ans = d[a]);
        }
    }
    return 0;
}
View Code

 

bzoj4668