您的位置:首页 > 其它

hdu5443The Water Problem 并查集

2015-09-15 21:37 281 查看
//给一个无向图
//每条边有对应的权值,问对于权值不能大于x的所有
//有多少对互相能到达的点
//直接记录下所有边,按权值大小排序
//然后将所有询问离线,排序
//对于小于x的所有边,用并查集将它们连接在一起
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std ;
const int maxm = 1e5+10 ;
const int maxn = 2e4+10 ;
int vis[maxn] ;
int F[maxn];
int sum[maxn] ;
int ans = 0 ;
int find(int x)
{
    if(F[x] == -1)
    return x ;
    return F[x] = find(F[x]) ;
}
void join(int x , int y)
{
    int fx = find(x) ;
    int fy = find(y) ;
    if(fx == fy)
    return  ;
    F[fx] = fy ;
    ans += sum[fx]*sum[fy]*2 ;
    sum[fy] += sum[fx] ;
    sum[fx] = 0 ;
}
pair<int, int>q[maxn] ;
struct node
{
    int u , v , w ;
    bool operator < (struct node tmp)const
    {
        return w < tmp.w ;
    }
}edge[maxm<<1] ;
int a[maxn] ;
int main()
{
    int t ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n , m , Q ;
        scanf("%d%d%d" ,&n , &m , &Q)  ;
        memset(F , -1, sizeof(F)) ;
        for(int i = 1;i <= n;i++)
        sum[i] = 1 ;
        for(int i = 1;i <= m;i++)
        scanf("%d%d%d" , &edge[i].u , &edge[i].v , &edge[i].w) ;
        sort(edge+1 , edge+1+m) ;
        for(int i = 1;i <= Q;i++)
        {
            int tmp ;
            scanf("%d" ,&tmp) ;
            q[i] = make_pair(tmp , i) ;
        }
        sort(q+1 , q+1+Q) ;
        ans = 0 ;
        int j = 1 ;
        for(int i = 1;i <= Q;i++)
        {
            while(edge[j].w <= q[i].first && j <= m)
            join(edge[j].u , edge[j].v) ,j++;
            a[q[i].second] = ans ;
        }
        for(int i = 1;i <= Q;i++)
        cout<<a[i]<<endl;
    }
    return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: