社区讨论

用lct的能否看下

P3366【模板】最小生成树参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mi6o3pgq
此快照首次捕获于
2025/11/20 08:02
4 个月前
此快照最后确认于
2025/11/20 08:02
4 个月前
查看原帖
实在没想明白我把次小生成树的lct做法稍微改下交到这里,竟然只跑300ms。我用本题题解做的lct跑了2s啊,为什么 下附代码(我甚至不知道这个做法是不是对的```cpp
CPP
#include <bits/stdc++.h>
#define maxn 301000
using namespace std ;
struct edge{
    int x , y , v ;
}ed[ 300100 ];
int c[ maxn + 101000 ][ 2 ] , fa[ maxn + 101000] , q[ maxn ] , rev[ maxn + 101000 ] , bing[ maxn + 101000 ] ;
int mx[ maxn + 101000 ] , mx2[ maxn + 101000 ] , v[ maxn + 101000 ] , n , m ,delta = 0x7fffffff;
long long ans = 0  ;
int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
bool isroot ( int x )//lct中判断一个节点是不是其整棵树的树根就看他父节点是不是0 
{//lct中判断其是不是所在splay的树根就看 下面一行 
    return c[ fa[ x ] ][ 0 ] != x && c[ fa[ x ] ][ 1 ] != x;
}
void up ( int x )//由于求严格次小生成树(大小一定比mst小) ,故要维护次小值 
{
    int l = c[ x ][ 0 ] , r = c[ x ][ 1 ] ;
    if ( mx[ l ] > mx[ r ] ) mx[ x ] = mx[ l ] , mx2[ x ] = max ( mx[ r ] , mx2[ l ] ) ;
    else if ( mx[ r ] > mx[ l ] ) mx[ x ] = mx[ r ] , mx2[ x ] = max ( mx[ l ] , mx2[ r ] ) ;
    else mx[ x ] = mx[ l ] , mx2[ x ] = max ( mx2[ l ] , mx2[ r ] ) ;
    if ( v[ x ] > mx[ x ] ) mx2[ x ] = mx[ x ] , mx[ x ] = v[ x ] ;
    else if ( v[ x ] > mx2[ x ] && v[ x ] != mx[ x ] ) mx2[ x ] = v[ x ] ;
    
}
void down ( int x )
{
    if ( ! rev[ x ] ) return ;
    swap ( c[ x ][ 0 ] , c[ x ][ 1 ] ) ;
    rev[ c[ x ][ 0 ] ] ^= 1 ;
    rev[ c[ x ][ 1 ] ] ^= 1 ;
    rev[ x ] = 0 ;
}
void rotate ( int x )
{
    int y = fa[ x ] , z = fa[ y ] , k = c[ y ][ 0 ] == x ;
    if ( ! isroot ( y ) ) c[ z ][ c[ z ][ 1 ] == y ] = x ;
    fa[ x ] = z ;
    c[ y ][ k ^ 1 ] = c[ x ][ k ] ;
    if ( c[ x ][ k ] ) fa[ c[ x ][ k ] ] = y ;
    c[ x ][ k ] = y ;
    fa[ y ] = x ;  
    up ( y ) ; up ( x ) ; 
}
void splay ( int x )
{
    int tp = 1 ; q[ tp ] = x ;
    for ( int i = x ; ! isroot ( i ) ; i = fa[ i ] ) q[ ++ tp ] = fa[ i ] ;
    for ( int i = tp ; i ; i -- ) down ( q[ i ] ) ; 
    while ( ! isroot ( x ) )
    {
        int y = fa[ x ] , z = fa[ y ] ;
        if ( ! isroot ( y ) )
            ( c[ z ][ 0 ] == y ) ^ ( c[ y ][ 0 ] == x ) ? rotate ( x ) : rotate ( y ) ;
        rotate ( x ) ;
    }
}
void access ( int x )
{
    for ( int i = 0 ; x ; i = x , x = fa[ x ] )
        splay ( x )	, c[ x ][ 1 ] = i , up ( x ) ;
}
int fin ( int x )
{
    if ( bing[ x ] != x ) bing[ x ] = fin ( bing[ x ] ) ;
    return bing[ x ] ;
}
void become_root ( int x )
{
    access ( x ) ; splay ( x ) ;
    rev[ x ] ^= 1 ; 
}
void link ( int x , int y )
{
   // if ( fin ( x ) == fin ( y ) ) return ; 
    become_root ( x ) ; fa[ x ] = y ;
}
void cut ( int x , int y )
{
   // if ( fin ( x ) != fin ( y ) ) return ;
    become_root ( x ) ; access ( y ) ; splay ( y ) ; fa[ x ] = 0 ; c[ y ][ 0 ] = 0 ;
    up( y ) ; 
}
bool cmp (edge x , edge y )
{
    return x.v < y.v ;
}
int main()
{
    int x , y , z , tot = 0 ;
    n = read () ; m = read () ; 
    for ( int i = 1 ; i <= n ; i ++ )
    	bing[ i ] = i ;
    for ( int i = 1 ; i <= m ; i ++ )
    	ed[ i ].x = read () , ed[ i ].y = read () , ed[ i ].v = read () , v[ i + n ] = ed[ i ].v ;
    sort ( ed + 1 , ed + m + 1, cmp ) ;
    for ( int i = 1 ; i <= m ; i ++ )
    {
    	x = ed[ i ].x ; y = ed[ i ].y ; z = ed[ i ].v ;
        if ( fin ( x ) == fin ( y ) )
        {; 
            //become_root ( x ) ; access( y ) ; splay ( y ) ;
           // delta = min ( delta , z - ( z > mx[ y ] ? mx[ y ] : mx2[ y ] ) ) ;/就是这里注释掉了 
        } 
        else 
    	{
            ans += z ; mx[ i + n ] = z ; v[ i + n ] = z ;
            link ( x , n + i ) ;
            link ( y , n + i ) ;	
            bing[ fin( x ) ] = fin( y ) ;											
        }

    }
    cout << ans ;
    return 0 ;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...