3938 Portal(离线型的并查集)

/*

    题意: 给出一个L  找出有多少条路径符合条件(条件为路径中路的最大值《=L)

    做了这个题学到了离线这个概念  离线就是  输入完成后进行操作 在线是变输入边操作

    用并查集来构图 , 每当遇到2棵树合并时, num[x]*num[y]是新的路径数

*/

#include<cstdio>

#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;


int n,m,q;
int p[10010],num[10010];
struct E
{
    int u,v,d;
    bool operator <(const E & ss) const
    {
        return d<ss.d;
    }
} a[50010];
struct QU
{
    int id,l;
    bool operator <(const QU & ss) const
    {
        return l<ss.l;
    }
} b[10010];
int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);
}
int Union(int x,int y)
{
    int px=find(x);
    int py=find(y),t=0;
    if(px!=py)
    {
        p[py]=px;
        t=num[px]*num[py];
        num[px]+=num[py];
    }
    return t;
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        for(int i =0; i <= n; i++)
        {
            p[i] = i;
            num[i] = 1;
        }
        for(int i = 0; i < m; i++)
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].d);
        for(int i = 0; i < q; i++)
        {
            scanf("%d",&b[i].l);
            b[i].id = i;
        }
        sort(a,a+m);
        sort(b,b+q);
        int j = 0,ans=0,out[10010];
        for(int i = 0; i < q; i++)
        {
            //printf("%d..\n",b[i].l);
            while(j<m&&a[j].d<=b[i].l)
            {
                ans+=Union(a[j].u,a[j].v);
                j++;
            }
            out[b[i].id]=ans;
        }
        for(int i = 0; i < q; i++)
            printf("%d\n",out[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/javawebsoa/p/3030650.html