现在的位置: 首页 > 综合 > 正文

【HDU】3938 Portal 并查集

2017年10月15日 ⁄ 综合 ⁄ 共 1472字 ⁄ 字号 评论关闭

传送门:【HDU】3938 Portal

题目分析:并查集离线处理即可。当然你要知道怎么计数吐舌头

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REPV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define clear( a , x ) memset ( a , x , sizeof a )

const int MAXN = 10005 ;
const int MAXM = 50005 ;
const int MAXE = 10005 ;
const int INF = 0x3f3f3f3f ;

struct Edge {
	int idx , n ;
	Edge () {}
	Edge ( int __idx , int next ) :
		idx ( __idx ) ,  n ( next ) {}
} ;

struct Node {
	int u , v , c ;
	void input () {
		scanf ( "%d%d%d" , &u , &v , &c ) ;
	}
	bool operator < ( const Node &a ) const {
		return c < a.c ;
	}
} ;

Edge E[MAXE] ;
int hd[MAXM] , cntE ;
Node A[MAXM] ;
int a[MAXM] ;
int p[MAXN] ;
int num[MAXN] ;
int ask[MAXN] ;
int n , m , q ;

int find ( int x ) {
	return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ;
}

void addedge ( int u , int v ) {
	E[cntE] = Edge ( v , hd[u] ) ;
	hd[u] = cntE ++ ;
}

int unique ( int a[] , int n ) {
	int cnt = 1 ;
	sort ( a + 1 , a + n + 1 ) ;
	REPF ( i , 2 , n )
		if ( a[i] != a[cnt] )
			a[++ cnt] = a[i] ;
	return cnt ;
}

int binary_search ( int x , int l , int r ) {
	while ( l < r ) {
		int m = ( l + r ) >> 1 ;
		if ( a[m] >= x )
			r = m ;
		else 
			l = m + 1 ;
	}
	return a[l] == x ? l : l - 1 ;
}

void work () {
	int cnt = 0 ;
	int ans = 0 ;
	int x , y , c ;
	cntE = 0 ;
	clear ( hd , -1 ) ;
	REPF ( i , 1 , n )
		p[i] = i , num[i] = 1 ;
	REP ( i , m ) {
		A[i].input () ;
		a[++ cnt] = A[i].c ;
	}
	cnt = unique ( a , cnt ) ;
	sort ( A , A + m ) ;
	REP ( i , q ) {
		scanf ( "%d" , &c ) ;
		addedge ( binary_search ( c , 1 , cnt + 1 ) , i ) ;
	}
	int j = 0 ;
	REPF ( i , 1 , cnt ) {
		while ( j < m && A[j].c <= a[i] ) {
			x = find ( A[j].u ) ;
			y = find ( A[j].v ) ;
			if ( x != y ) {
				ans -= num[x] * ( num[x] + 1 ) / 2 ;
				ans -= num[y] * ( num[y] + 1 ) / 2 ;
				num[y] += num[x] ;
				ans += num[y] * ( num[y] + 1 ) / 2 ;
				p[x] = y ;
			}
			++ j ;
		}
		for ( int o = hd[i] ; ~o ; o = E[o].n )
			ask[E[o].idx] = ans ;
	}
	REP ( i , q )
		printf ( "%d\n" , ask[i] ) ;
}

int main () {
	while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
		work () ;
	return 0 ;
}

抱歉!评论已关闭.