CodeForces - 827D [Best Edge Weight] 倍增+最小生成树+并查集

# include <vector>
# include <cstdio>
# include <cstring>
# include <iostream>
# include <algorithm>
# define Name "weight"

using namespace std ;

inline int Read () {
    int x = 0 , f = 1 ;
    char ch = getchar () ;
    while ( ! isdigit ( ch ) ) {
        if ( ch == '-' ) f = - 1;
        ch = getchar () ;
    }
    while ( isdigit ( ch ) ) {
        x = x * 10 + ch - '0' ;
        ch = getchar () ;
    }
    return x * f ;
}
const int N = 2e5 + 10 ;
const int Inf = 0x3f3f3f3f ;
struct Edge {
    int id ;
    int u , v , w ;
    Edge ( int x = 0 , int y = 0 , int z = 0 ) : v ( x ) , w ( y ) , id ( z ) {}
} e [N] ;

vector <Edge> edges ;
vector <int> G [N] ;

int ans [N] , fa [N] [20] , dep [N] , st [N] [20] , used [N] , f [N] , to [N] ;
int n , m ;

void addeage ( int u , int v , int w , int id ) {
    edges.push_back ( Edge ( v , w , id ) ) ;
    int tot = edges.size () ;
    G [u].push_back ( tot - 1 ) ; 
}

void dfs ( int u , int fat ) {
    fa [u] [0] = fat ;
    for ( int i = 1 ; i <= 18 ; ++ i ) 
        fa [u] [i] = fa [ fa [u] [ i - 1 ] ] [ i - 1 ] ,
        st [u] [i] = max ( st [u] [ i - 1 ] , st [ fa [u] [ i - 1 ] ] [ i - 1 ] ) ;
    for ( int i = 0 ; i < G [u].size () ; ++ i ) {
        Edge e = edges [ G [u] [i] ] ;
        if ( e.v == fat ) continue ;
        to [e.v] = e.id ;
        st [e.v] [0] = e.w ;
        dep [e.v] = dep [u] + 1 ;
        dfs ( e.v , u ) ;
    }
}

int LCA ( int u , int v , int & d ) {
    d = 0 ;
    if ( dep [u] < dep [v] ) swap ( u , v ) ;
    int t = dep [u] - dep [v] ;
    for ( int i = 0 ; i <= 18 ; ++ i ) 
        if ( ( 1 << i ) & t ) {
            d = max ( d , st [u] [i] ) ;
            u = fa [u] [i] ;
        }
    if ( u == v ) return u ;
    for ( int i = 18 ; i >= 0 ; -- i ) {
        if ( fa [u] [i] != fa [v] [i] ) {
            d = max ( d , max ( st [u] [i] , st [v] [i] ) ) ;
            u = fa [u] [i] ;
            v = fa [v] [i] ;
        }
    }

    d = max ( d , max ( st [u] [0] , st [v] [0] ) ) ; 
    return fa [u] [0] ;
}

int getfa ( int u ) {
    return ( u == f [u] ) ? u : f [u] = getfa ( f [u] ) ;
}

bool cmp ( Edge x , Edge y ) {
    return x.w < y.w ;
}
void KrusKal () {
    int tot = 0 ;
    sort ( e + 1 , e + 1 + m , cmp ) ;
    for ( int i = 1 ; i <= m ; ++ i ) {
        int u = e [i].u , v = e [i].v ;
        int u1 = getfa ( u ) , v1 = getfa ( v ) ;
        if ( u1 != v1 ) {
            f [u1] = v1 ;   
            used [i] = 1 ;
            addeage ( u , v , e [i].w , e [i].id ) ;
            addeage ( v , u , e [i].w , e [i].id ) ;
            tot ++ ;
        }
        if ( tot == n - 1 ) break ;
    }   
}

void modify ( int u , int v , int d ) {
    u = getfa ( u ) ;
    while ( dep [u] > dep [v] ) {
        ans [ to [u] ] = min ( ans [ to [u] ] , d ) ;
        int y = getfa ( fa [u] [0] ) ;
        f [u] = y ;
        u = getfa ( u ) ;
    }
}

int main () {
//  freopen ( Name ".in" , "r" , stdin ) ;
    scanf ( "%d%d" , & n , & m ) ;
    for ( int i = 1 ; i <= m ; ++ i ) {
        int u , v , w ;
        e [i].u = Read () , e [i].v = Read () , e [i].w = Read () , e [i].id = i ;
    }
    for ( int i = 1 ; i <= n ; ++ i ) f [i] = i ;

    KrusKal () ;
    dfs ( 1 , 1 ) ;
    memset ( ans , Inf , sizeof ans ) ;
    for ( int i = 1 ; i <= n ; ++ i ) f [i] = i ;

    for ( int i = 1 ; i <= m ; ++ i ) {
        if ( used [i] ) continue ;
        int u = e [i].u , v = e [i].v ;
        int ffa = LCA ( u , v , ans [ e [i].id ] ) ;
        ans [ e [i].id ] -- ;
        modify ( u , ffa , e [i].w - 1 ) ;
        modify ( v , ffa , e [i].w - 1 ) ;
    }
    for ( int i = 1 ; i <= m ; ++ i ) 
        if ( ans [i] == Inf ) printf ( "-1 " ) ;
        else printf ( "%d " , ans [i] ) ;
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值