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( "
" );
	return 0;
}
原文地址:https://www.cnblogs.com/chy-2003/p/11479442.html