hdu 3938 Portal 计算两点路上最大距离中的最小值<=L的路径个数 离线并查集

Problem Description
ZLGG found a magic theory that the bigger banana the bigger banana peel .This important theory can help him make a portal in our universal. Unfortunately, making a pair of portals will cost min{T} energies. T in a path between point V and point U is the length of the longest edge in the path. There may be lots of paths between two points. Now ZLGG owned L energies and he want to know how many kind of path he could make.
 

Input
There are multiple test cases. The first line of input contains three integer N, M and Q (1 < N ≤ 10,000, 0 < M ≤ 50,000, 0 < Q ≤ 10,000). N is the number of points, M is the number of edges and Q is the number of queries. Each of the next M lines contains three integers a, b, and c (1 ≤ a, b ≤ N, 0 ≤ c ≤ 10^8) describing an edge connecting the point a and b with cost c. Each of the following Q lines contain a single integer L (0 ≤ L ≤ 10^8).
 

Output
Output the answer to each query on a separate line.
 

Sample Input
  
  
10 10 10 7 2 1 6 8 3 4 5 8 5 8 2 2 8 9 6 4 5 2 1 5 8 10 5 7 3 7 7 8 8 10 6 1 5 9 1 8 2 7 6
 

Sample Output
  
  
36 13 1 13 36 1 36 2 16 13

//


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//按照边大小排序,依次合并两端点,则以此边为路上最大长度
//的路径共有 num[x]*num[y];
//将要查询的L从小到大排序,依次处理即可
const int maxn=51000;
int fath[maxn];
int num[maxn];
int n;
void init()
{
    for(int i=1;i<=n;i++) fath[i]=i,num[i]=1;
}
int find(int x)
{
    return fath[x]==x?x:fath[x]=find(fath[x]);
}
int uion(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y) return 0;
    int cnt=num[x]*num[y];
    if(num[x]<num[y])
    {
        fath[x]=y;
        num[y]+=num[x];
    }
    else
    {
        fath[y]=x;
        num[x]+=num[y];
    }
    return cnt;
}
struct Edge
{
    int u,v,w;
};
Edge edge[maxn];
bool cmpEdge(Edge h,Edge k)
{
    return h.w<k.w;
}
struct Node
{
    int val;
    int index;
};
Node ind[maxn];
bool cmpNode(Node h,Node k)
{
    return h.val<k.val;
}
int ans[maxn];
int main()
{
    int m,q;
    while(scanf("%d%d%d",&n,&m,&q)==3)
    {
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        sort(edge,edge+m,cmpEdge);
        for(int i=0;i<q;i++)
        {
            scanf("%d",&ind[i].val);
            ind[i].index=i;
        }
        sort(ind,ind+q,cmpNode);
        init();
        int sum=0;
        int l=0;
        for(int i=0;i<m;i++)
        {
            int u=edge[i].u,v=edge[i].v,w=edge[i].w;
            int tmp=uion(u,v);
            sum+=tmp;
            while(l<q&&w>ind[l].val) ans[ind[l++].index]=sum-tmp;
        }
        for(int i=l;i<q;i++) ans[ind[i].index]=ans[ind[i-1].index];
        for(int i=0;i<q;i++) printf("%d\n",ans[i]);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值