5060. 公路建设

来源:互联网 发布:上海网络交换机回收 编辑:程序博客网 时间:2024/06/16 20:29

题目大意

给定n个点,m条边,每条边有边权。
q个询问,每个询问询问用编号为[li,ri]之间的边构最小生成森林的权值和。

Data Constraint
n100,m100000,q15000

题解

考虑对边建线段树,每个区间维护在最小生成森林上的边,显然最多只有n1条边。
然后每次合并区间就直接用Kruskal重构。

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std ;#define N 100000 + 10typedef long long ll ;struct Edge {    int u , v , w ;} E[N] ;struct Tree {    vector < int > e ;} T[4*N] ;vector < int > tp ;int fa[N] ;int n , m , Q ;int Get( int x ) { return fa[x] == x ? x : fa[x] = Get(fa[x]) ; }void Merge( int l , int r ) {    tp.clear() ;    int h1 = 0 , h2 = 0 ;    int siz1 = T[l].e.size() , siz2 = T[r].e.size() ;    while ( h1 < siz1 || h2 < siz2 ) {        if ( h1 < siz1 && h2 < siz2 ) {            if ( E[T[l].e[h1]].w < E[T[r].e[h2]].w ) {                tp.push_back(T[l].e[h1]) ;                h1 ++ ;            } else {                tp.push_back(T[r].e[h2]) ;                h2 ++ ;            }        } else {            if ( h1 < siz1 ) {                tp.push_back(T[l].e[h1]) ;                h1 ++ ;            } else {                tp.push_back(T[r].e[h2]) ;                h2 ++ ;            }        }    }}void Kruskal( int now ) {    T[now].e.clear() ;    for (int i = 1 ; i <= n ; i ++ ) fa[i] = i ;    for (int i = 0 ; i < (signed)tp.size() ; i ++ ) {        int u = E[tp[i]].u , v = E[tp[i]].v ;        int fx = Get(u) ;        int fy = Get(v) ;        if ( fx != fy ) {            T[now].e.push_back(tp[i]) ;            fa[fx] = fy ;        }    }}void Build( int v , int l , int r ) {    if ( l == r ) {        T[v].e.push_back(l) ;        return ;    }    int mid = (l + r) >> 1 ;    Build( v + v , l , mid ) ;    Build( v + v + 1 , mid + 1 , r ) ;    Merge( v + v , v + v + 1 ) ;    Kruskal( v ) ;}void Search( int v , int l , int r , int x , int y ) {    if ( l == x && r == y ) {        Merge( 0 , v ) ;        Kruskal(0) ;        return ;    }    int mid = (l + r) >> 1 ;    if ( y <= mid ) Search( v + v , l , mid , x , y ) ;    else if ( x > mid ) Search( v + v + 1 , mid + 1 , r , x , y ) ;    else {        Search( v + v , l , mid , x , mid ) ;        Search( v + v + 1 , mid + 1 , r , mid + 1 , y ) ;    }}int main() {    freopen( "highway.in" , "r" , stdin ) ;    freopen( "highway.out" , "w" , stdout ) ;    scanf( "%d%d%d" , &n , &m , &Q ) ;    for (int i = 1 ; i <= m ; i ++ ) scanf( "%d%d%d" , &E[i].u , &E[i].v , &E[i].w ) ;    Build( 1 , 1 , m ) ;    for (int i = 1 ; i <= Q ; i ++ ) {        int l , r ;        scanf( "%d%d" , &l , &r ) ;        T[0].e.clear() ;        Search( 1 , 1 , m , l , r ) ;        ll ans = 0 ;        for (int i = 0 ; i < (signed)T[0].e.size() ; i ++ ) ans += E[T[0].e[i]].w ;        printf( "%lld\n" , ans ) ;    }    return 0 ;}

以上.

0 0
原创粉丝点击