This topic seems to be the topic of graph theory lecture in SD summer camp half a year ago. At that time, I was a real dish. I was dropping the line in a class, and I couldn't understand this topic.
But now it seems easier to write.
An undirected graph \ (G \) with \ (n \) points and \ (m \) edges is given, and the strict sub minor spanning tree \ (T '\) of the graph is obtained.
The definition of strictly sub small spanning tree is that the minimum spanning tree of \ (G \) is \ (t \), and its edge weight sum is \ (\ sigma(T) \), then \ (\ sigma (t ') > \ sigma(T) \) must be satisfied, and there is no spanning tree \ (t' '\) such that \ (\ sigma(T) < \ sigma (t' ') < \ sigma (t') \).
Let's first consider the non strict case, that is, the case where \ (\ sigma(T ') \) can be equal to \ (\ sigma(T) \).
First, the next small spanning tree \ (T '\) must change an edge based on the smallest spanning tree. It's obviously not better to change more edges than just one, right.
Then we consider enumerating each non tree edge \ (e\notin T \) into \ (T \), and there is a ring in which the weight of all tree edges on this ring is less than that of \ (e \). This inference is correct, because if not, \ (e \) should replace a \ (e '\) with a weight greater than \ (e \) in \ (T \).
At this time, in order to minimize this condition, we need to try to remove the largest tree edge \ (e_{\max} \) on this ring and find a new spanning tree \ (T_1 \), and the edge weight sum of this spanning tree \ (\ sigma(T_1)=\sigma(T)-w(e_{\max})+w(e) \).
Finding the maximum tree edge on a ring is the maintenance of the maximum edge weight on a chain, which can be multiplied directly on \ (T \), and can be maintained by LCT or tree section.
Then enumerate all non tree edges and find \ (\ min\{\sigma(T_1) \} \).
Then consider the strict situation. Due to inference, \ (w (E) \ GEQ w (E {\ Max}) \) is always true, but it can be divided into two cases when it is strict:
-
\(w (E) > W (E {\ Max}) \), at this time \ (\ sigma (t_1) < \ sigma (T) \) is legal, and the answer can be updated directly.
-
\(w (E) = w (E {\ Max}) \), at this time \ (\ sigma(T_1)=\sigma(T) \) is illegal. Consider maintaining another strict sub maximum value of edge weight \ (E {\ Max} '\). At this time \ (w (E) > W (e_{\max} ') \, so we can remove \ (E {\ Max}' \) from the ring to find \ (t _1 \), and at this time \ (t _1 \) meets \ (\ sigma (t _1) < \ sigma (T) \), \ (\ sigma(T_1)=\sigma(T) - w (E {\ Max} ') + W (E) \). You can update the answer directly.
Here I use Kruskal, tree section to maintain the complexity \ (O(m\log m+m\log^2n) \).
However, the method of maintaining strictly sub maximum values in some segment trees in the problem solving area is wrong. Here is a maintenance method through all hack data.
// _ max is the maximum value_ smax is strictly sub maximum inline pair< int , int >merge( pair< int , int >p , pair< int , int > q ){ int lv = p . _max , lsv = p . _smax; int rv = q . _max , rsv = q . _smax; pair< int , int >ret; if( lv > rv ) ret . _max = lv , lv = 0; else if( rv > lv ) ret . _max = rv , rv = 0; else ret . _max = lv , rv = lv = 0; ret . _smax = max( max( lv , rv ) , max( lsv , rsv ) ); return ret; }
Remember to judge the self ring, and I'm used to defining the maximum INF = 0x3f3f3f3f. In this way, WA on #10 will be opened, and long long will be changed to INF = 1e18.
# include <cstdio> # include <iostream> # include <algorithm> # include <utility> # include <vector> namespace IO{ inline int read(){ int ret = 0 , ti = 1; char u = getchar(); while( ! isdigit( u ) ){ if( u == '-' ) ti = -1; u = getchar(); } while( isdigit( u ) ) ret = ret * 10 + u - '0' , u = getchar(); return ret * ti; } } using namespace std; typedef long long ll; const ll INF = 1e18; const int N = 3e5 + 225; int n , m; ll ans = INF; //--------------------------------------------------- int ufa[ N ]; int find( int u ){ return ufa[ u ] == u ? u : ufa[ u ] = find( ufa[ u ] ); } //--------------------------------------------------- vector< pair< int , int > >E[ N ]; # define forE( u , i ) for( i = 0 ; i < E[ u ] . size() ; i ++ ) # define ldt( u, i ) E[ u ][ i ] . first # define val( u , i ) E[ u ][ i ] . second struct Edge{ int u , v , w; bool operator <( const Edge & p ) const{ return w < p . w; } }e[ N ]; //---------------------------------------------------- int vis[ N ]; ll mstw; void mst(){ sort( e + 1 , e + m + 1 ); for( int i = 1 ; i <= n ; i ++ ) ufa[ i ] = i; for( int i = 1 , cnt = 0 ; i <= m ; i ++ ){ int u = e[ i ] . u , v = e[ i ] . v , w = e[ i ] . w; int fu = find( u ) , fv = find( v ); if( fu != fv ){ ufa[ fu ] = fv , cnt ++ , mstw += ( ll ) w , vis[ i ] = 1; E[ u ] . push_back( make_pair( v , w ) ); E[ v ] . push_back( make_pair( u , w ) ); if( cnt == n - 1 ) break; } } } //---------------------------------------------------- int fa[ N ] , idx[ N ] , tidx[ N ] , ch[ N ] , siz[ N ] , dep[ N ] , s[ N ] , tp[ N ] , nod; void dfs1( int u , int f ){ fa[ u ] = f , dep[ u ] = dep[ f ] + 1 , siz[ u ] = 1; int i; forE( u , i ){ int v = ldt( u , i ) , w = val( u , i ); if( v == f ) continue; s[ v ] = w , dfs1( v , u ) , siz[ u ] += siz[ v ]; if( siz[ v ] > siz[ ch[ u ] ] ) ch[ u ] = v; } } void dfs2( int u , int top ){ tp[ u ] = top , idx[ u ] = ++ nod , tidx[ nod ] = u; if( ch[ u ] ) dfs2( ch[ u ] , top ); int i; forE( u , i ){ int v = ldt( u , i ); if( v == fa[ u ] || v == ch[ u ] ) continue; dfs2( v , v ); } } //-------------------------------------------------------- pair< int , int >t[ N << 3 ]; # define lefc( u ) u << 1 # define rigc( u ) u << 1 | 1 # define _max first # define _smax second inline pair< int , int >merge( pair< int , int >p , pair< int , int > q ){ int lv = p . _max , lsv = p . _smax; int rv = q . _max , rsv = q . _smax; pair< int , int >ret; if( lv > rv ) ret . _max = lv , lv = 0; else if( rv > lv ) ret . _max = rv , rv = 0; else ret . _max = lv , rv = lv = 0; ret . _smax = max( max( lv , rv ) , max( lsv , rsv ) ); return ret; } void push_up( int u ){ int lc = lefc( u ) , rc = rigc( u ); t[ u ] = merge( t[ lc ] , t[ rc ] ); } void build( int u , int l , int r ){ if( l == r ){ t[ u ] = make_pair( s[ tidx[ l ] ] , 0 ); return; } int mid = l + r >> 1; build( lefc( u ) , l , mid ); build( rigc( u ) , mid + 1 , r ); push_up( u ); } pair< int , int >query( int u , int l , int r , int L , int R ){ if( L <= l && r <= R ) return t[ u ]; int mid = l + r >> 1; pair< int , int >ret; if( R <= mid ) return query( lefc( u ) , l , mid , L , R ); if( L > mid ) return query( rigc( u ) , mid + 1 , r , L , R ); return merge( query( lefc( u ) , l , mid , L , R ) , query( rigc( u ) , mid + 1 , r , L , R ) ); } //---------------------------------------------- pair< int , int >operatq( int u , int v ){ pair< int , int >ret; while( tp[ u ] != tp[ v ] ){ if( dep[ tp[ u ] ] < dep[ tp[ v ] ] ) swap( u , v ); ret = merge( ret , query( 1 , 1 , n , idx[ tp[ u ] ] , idx[ u ] ) ); u = fa[ tp[ u ] ]; } if( u == v ) return ret; if( dep[ u ] > dep[ v ] ) swap( u , v ); ret = merge( ret , query( 1 , 1 , n , idx[ u ] + 1 , idx[ v ] ) ); return ret; } void solve(){ for( int i = 1 ; i <= m ; i ++ ){ int u = e[ i ] . u , v = e[ i ] . v , w = e[ i ] . w; if( ! vis[ i ] && u != v ){ pair< int , int >p = operatq( u , v ); if( w == p . _max && p . _smax ) ans = min( ans , ( ll ) mstw - p . _smax + w ); else if( w > p . _max ) ans = min( ans , ( ll ) mstw - p . _max + w ); } } printf( "%lld\n" , ans ); } void input(){ n = IO :: read() , m = IO :: read(); for( int i = 1 ; i <= m ; i ++ ) e[ i ] . u = IO :: read() , e[ i ] . v = IO :: read() , e[ i ] . w = IO :: read(); } int main(){ input(); mst(); dfs1( 1 , 0 ); dfs2( 1 , 1 ); build( 1 , 1 , n ); solve(); system( "pause" ); return 0; }