hdu5441&15年长春网赛1005

题目大意:有一n个点,m条边的带边权的图,然后给出q个问题,每个问题会给一个边权的量,在图中,超出这个边权,就算不连通,问在判断不连通之后,图中还有多少对连通的点?

解题思路:并查集,此时每个结点的秩为它的子节点的数目~~

注意点:

1.让边以边权从小到大排序,然问题按照提供的边权的排序。(这两个优化很重要,不用每次都去重新扫)

2.两个连通块合并之后,其大小是2*rank_num[u]*rank_num[v];

代码转自http://blog.csdn.net/qq_24451605/article/details/48415749

我的代码弄丢了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 20007

using namespace std;

int fa[MAX],num[MAX],t,n,m,q,pp[MAX];

struct Query
{
    int x,id;
    bool operator < ( const Query& a )const 
    {
        return x < a.x;
    }
}a[MAX];


struct Edge
{
    int u,v,w;
    bool operator < ( const Edge& a ) const 
    {
        return w < a.w;
    }
}e[MAX*5];

void init ( )
{
    for ( int i = 1 ; i <= n ; i++ )
    {
        num[i] = 1;
        fa[i] = i;
    }
}

int _find ( int x )
{
    return fa[x] == x? x : fa[x] = _find ( fa[x] );
}

void _union ( int x , int y )
{
    x = _find ( x );
    y = _find ( y );
    if ( y < x ) swap ( x , y );
    fa[y] = x;
    num[x] += num[y];
}

int main ( )
{
    scanf ( "%d" ,&t );
    while ( t-- )
    {
        int ans = 0;
        scanf ( "%d%d%d" , &n , &m , &q );
        init ( ); 
        for ( int i = 0 ; i < m ; i++ )
            scanf ( "%d%d%d" , &e[i].u , &e[i].v , &e[i].w );
        sort ( e , e+m );
        int j = 0;
        for ( int i = 0 ; i < q ; i++ )
        {
            a[i].id = i;
            scanf ( "%d" , &a[i].x );
        }
        sort ( a , a+q );
        for ( int i = 0 ; i < q ; i++ )
        {
            while ( j < m && e[j].w <= a[i].x )
            {
                int u = _find ( e[j].u );
                int v = _find ( e[j].v );
                j++;
                if ( u == v ) continue;
                ans += (num[u]+num[v])*(num[u]+num[v]-1)-num[u]*(num[u]-1) - num[v]*(num[v]-1);
                _union ( u , v );
            }
            pp[a[i].id] = ans;
        }
        for ( int i = 0 ; i < q ; i++ )
            printf ( "%d\n" , pp[i] );
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值