zoukankan      html  css  js  c++  java
  • hdu 离线处理+并查集

    给你力量L,求有多少条path的力量小于等于L。

    这个path消耗的力量是T,T是U到V上最长的边。

    所以说,只要求得有多少个点对使得点对之间的最大的边小于L即可。

    采用并查集,离线计算,询问从小到大排序,然后边从小到大排序,然后一个一个加入并查集中,加一条,计算一次两个集合的点的数目的乘积即可。

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <utility>
    #define inf (1<<28)
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=10010;
    const int M=50002;
    struct Node {
        int u,v,len;
    }edge[M];
    int cmp(Node a,Node b){return a.len<=b.len;}
    int fa[N],sum[N];
    int n,m,q;
    void init()
    {
        for(int i=1;i<=n;i++){fa[i]=i;sum[i]=1;}
    }
    
    int findx(int x)
    {
        return fa[x]=fa[x]==x?x:findx(fa[x]);
    }
    
    
    int Union(int a,int b){
        int aa=findx(a);
        int bb=findx(b);
        //if(aa==bb)return 0;
        if(fa[aa]<fa[bb])
        {
            fa[bb]=aa;
            int tmp=sum[aa]*sum[bb];
            sum[aa]+=sum[bb];
            //cout<<" ____"<<tmp<<endl;
            return tmp;
        }
        else {
            fa[aa]=bb;
            int tmp=sum[aa]*sum[bb];
            sum[bb]+=sum[aa];
            //cout<<" ____"<<tmp<<endl;
            return tmp;
        }
    }
    int ans[N];
    struct Q{
        int L,id,ans;
    }que[N];
    
    bool cmp1(Q a,Q b){return a.L<=b.L;}
    bool cmp2(Q a,Q b){return a.id<b.id;}
    
    int main()
    {
        while(scanf("%d%d%d",&n,&m,&q)!=EOF){
            init();
            for(int i=0;i<m;i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].len);
            for(int i=0; i<q; i++)
                {scanf("%d",&que[i].L);que[i].id=i;que[i].ans=0;}
            sort(edge,edge+m,cmp);
            sort(que,que+q,cmp1);
            int cnt=0;
            for(int i=0;i<q;i++){
                while(edge[cnt].len<=que[i].L&&cnt<m)
                {
                    int aa=findx(edge[cnt].u);
                    int bb=findx(edge[cnt].v);
                    if(aa==bb)
                    {
                        cnt++;
                        continue;
                    }
                    else{
                        //cout<<"------------"<<sum[aa]<<" "<<sum[bb]<<endl;
                        que[i].ans+=Union(edge[cnt].u,edge[cnt].v);cnt++;
                        //cout<<Union(edge[i].u,edge[i].v)<<endl;
                    }
                }
                if(i>=1)que[i].ans+=que[i-1].ans;//这里之前放在循环里面调了好久。。。
            }
            sort(que,que+q,cmp2);//还原之前的序列
            for(int i=0; i<q; i++)
            {
               printf("%d
    ",que[i].ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Python之格式化unix时间戳
    Python简单的验证码生成
    Python字符串常用的一些东西
    PHP explode()函数
    PHP函数number_format()
    PHP简单的计算位数的函数
    python之列表推导式
    python之把列表当做队列使用
    python之列表操作的几个函数
    python之map函数
  • 原文地址:https://www.cnblogs.com/wlxtuacm/p/5712277.html
Copyright © 2011-2022 走看看