CF1213G Path Queries

题目链接

问题分析

直接按边从小到大加入,求所有的连通点对数量即可。最后离线询问。使用并查集维护Size。

参考程序

#include <bits/stdc++.h>
using namespace std;

const int Maxn     = 200010;
const int MaxAlpha = 200000;
struct edge {
    int u, v, w;
    edge() {}
    edge( int _u, int _v, int _w ) : u( _u ), v( _v ), w( _w ) {}
    inline bool operator < ( const edge Other ) const {
        return w < Other.w;
    }
};
edge Edge[ Maxn ];
int n, m, Father[ Maxn ], Size[ Maxn ];
long long Count, Ans[ Maxn ];

int GetFather( int x ) {
    if( Father[ x ] == x ) return x;
    Father[ x ] = GetFather( Father[ x ] );
    return Father[ x ];
}

void Add( int x ) {
    int a = GetFather( Edge[ x ].u );
    int b = GetFather( Edge[ x ].v );
    Count += 1LL * Size[ a ] * Size[ b ];
    Father[ a ] = b;
    Size[ b ] += Size[ a ];
    return;
}

int main() {
    scanf( "%d%d", &n, &m );
    for( int i = 1; i < n; ++i ) {
        int x, y, z;
        scanf( "%d%d%d", &x, &y, &z );
        Edge[ i ] = edge( x, y, z );
    }
    for( int i = 1; i <= n; ++i ) Father[ i ] = i, Size[ i ] = 1;
    sort( Edge + 1, Edge + n );
    for( int i = 1; i < n; ++i ) {
        Add( i );
        for( ; Edge[ i ].w == Edge[ i + 1 ].w && i < n; ++i ) Add( i + 1 );
        Ans[ Edge[ i ].w ] = Count;
    }
    for( int i = 1; i <= MaxAlpha; ++i ) Ans[ i ] = max( Ans[ i ], Ans[ i - 1 ] );
    for( int i = 1; i <= m; ++i ) {
        int x;
        scanf( "%d", &x );
        printf( "%lld ", Ans[ x ] );
    }
    printf( "\n" );
    return 0;
}
posted @ 2019-09-07 10:29 chy_2003 阅读(...) 评论(...) 编辑 收藏