• hdu5441


    题目描述:

    在一张图中求出有多少对这样的点满足a关系?

    a:相连并且路径上直接相连的两个点的边的权值小于给定的某个值,假设是x

    因为询问不确定,所以可以先读取询问操作,按照我们想要的方式回答,然后按照原始顺序输出。

    相连并且直接相连的每条边的权值小于x的点为一个集合,在这个集合中满足条件的点对有A(2,5)

    假设给定的x大于这张图中所有边的权值,那么满足条件的点对有A(2,n)种;

    但是x不确定,所以可以先给x从小到大排序,因为大x的答案肯定包含小x的答案,

    然后图中边的权值从小到大排序,由x将边分块回答,采用并查集将一条边相连的点合并。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define maxn 105000
    struct Edge
    {
        int from,to,dist;
    }edge[maxn];
    int n,m,q;
    int answer[maxn];
    struct node
    {
        int d,id;
    }que[5500];
    bool cmp1(Edge a,Edge b)
    {
        return a.dist<b.dist;
    }
    bool cmp2(node a,node b)
    {
        return a.d<b.d;
    }
    int fa[maxn];
    int Size[maxn];
    void init()
    {
         for(int i=1;i<=n;i++)
           {
               fa[i]=i;      //代表每个元素的父亲节点
               Size[i]=1;    //代表集合中有多少元素
           }
    }
    
    int Find(int x)
    {
       if(x!=fa[x])   fa[x]=Find(fa[x]);
       return fa[x];
    }
    void solve()
    {
        int ans=0;
        int j=1;
        for(int i=1;i<=q;i++)
        {
           for(;edge[j].dist<=que[i].d ;j++)
           {
                int from,to;
                from=edge[j].from;
                to=edge[j].to;
                if(from==to)
                  continue;
                int t1,t2;
                t1=Find(from);
                t2=Find(to);
                if(t1==t2)  //如果在一个集合,就不用合并
                    continue;
                ans+=2*Size[t1]*Size[t2];
                fa[t2]=t1;
                Size[t1]+=Size[t2];
           }
           answer[que[i].id]=ans;
        }
        for(int i=1;i<=q;i++)
            printf("%d
    ",answer[i]);
    }
    int main()
    {
        //freopen("test.txt","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&q);
            init();
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dist);
            }
            for(int i=1;i<=q;i++)
            {
                scanf("%d",&que[i].d);
                que[i].id=i;
            }
            sort(edge+1,edge+m+1,cmp1);
            sort(que+1,que+q+1,cmp2);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    开源软件的国内镜像
    ruby学习之路(一)
    VBS正则表达式
    fscanf和feof的组合使用
    计算机产生随机数
    常用:JQ
    unitegallery 测试使用-自动播放关闭
    H5重力感应(转)
    JS中,如何判断一个数是不是小数?如果是小数,如何判断它是几位小数 保留n位小数
    input禁止显示历史输入记录
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4817102.html
Copyright © 2020-2023  润新知