HDU 3938 Portal(并查集,离线)

Posted shuitiangong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3938 Portal(并查集,离线)相关的知识,希望对你有一定的参考价值。

题目链接

题目大意

??查询有多少对(x,y),使得x到y至少存在一条路径,路径上的边权值最大值不超过L。

解题思路

??从小到达依次枚举各个边,就能得到若干个图,图里的每条边都不大于当前的最大边(废话)。但是问题在于如何求出每次新加入一条边之后的点的对数,因为所有的边不一定是全都连接一起的。
??如果一条边把一个点连入一个图里的话,那么这个点与图里的每一个点都能形成一个新的点对,那么新增加的点对就是图中的点的个数。如果一条边把一个图与另外一个图相连呢?那么新增的点对就是两个图的点的个数之积。所以我们只要需要用一个并查集来维护所有点之间的关系和每个集合里的点的个数就行了。

代码

const int maxn = 1e4+10;
struct Q {
    int qs, num;
} q[maxn];
struct E {
    int u, v, w;
} e[5*maxn];
int n, m, qes, p[maxn], cnt[maxn], ans[maxn];
int find(int x) {
    return p[x] == x ? p[x] : p[x] = find(p[x]);
}
int main() {
    while(~scanf("%d%d%d",&n,&m,&qes)) {
        for (int i = 0; i<m; ++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        for (int i = 0; i<qes; ++i) {
            scanf("%d", &q[i].qs);
            q[i].num = i; ans[i] = 0;
        }
        sort(e, e+m, [](E a, E b) {return a.w<b.w;});
        sort(q, q+qes, [](Q a, Q b) {return a.qs<b.qs;});
        for (int i = 1; i<=n; ++i) {
            p[i] = i; cnt[i] = 1;
        }
        int k = 0, sum = 0;
        for (int i = 0; i<m; ++i) {
            while(k<qes&&q[k].qs<e[i].w) ans[q[k++].num] = sum;
            int fa = find(e[i].u), fb = find(e[i].v);
            if (fa!=fb) {
                sum += cnt[fa]*cnt[fb];
                cnt[fb] += cnt[fa];
                p[fa] = fb;
            }
        }
        while(k<qes&&q[k].qs>=e[m-1].w) ans[q[k++].num] = sum;
        for (int i = 0; i<qes; ++i) printf("%d
", ans[i]);
    }
    return 0;
}

以上是关于HDU 3938 Portal(并查集,离线)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3938 Portal(并查集,离线)

hdu 3938 (离线并查集)

HDU3938 Portal (并查集经典+最小生成树)

集合问题 离线+并查集 HDU 3938

HDU 3938 并查集

杭电OJ3938离线+并查集