Problem Statement
“Given an undirected graph G
with edge weights, output all edges that are
the heaviest edge in some cycle of G
”
Problem Link
Thought Process
Well, it’s a minimum spanning tree problem. Either Kruskal
’s or
Prim
’s algorithm should work fine here (Kruskal
’s is used below).
Instead of printing the edges of the minimum spanning tree itself, we should print
the edges that were not chosen by Kruskal
’s/Prim
’s algorithm. We can easily
do this by initializing a set, edges_set
, to contain all the weights of
the graph G
, and whenever we pick an edge to be part of our minimum spanning
tree, we removed it from the edges_set
At the end, we’re left with edges_set
that has all the edges that were
not picked, i.e the heaviest ones. Sort it and print its content.
Code
C++11 code below
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <functional>
using namespace std ;
int n , m ;
vector < pair < int , pair < int , int >>> EdgeList ;
multiset < int > edges_set ;
class UnionFind
{
vector < int > p , rank ;
public:
explicit UnionFind ( int N )
{
rank . assign ( N , 0 );
p . assign ( N , 0 );
for ( int i = 0 ; i < N ; i ++ ) p [ i ] = i ;
}
int findSet ( int i )
{ return ( p [ i ] == i ) ? i : ( p [ i ] = findSet ( p [ i ]) ); }
bool isSameSet ( int i , int j )
{ return findSet ( i ) == findSet ( j ); }
void unionSet ( int i , int j )
{
if ( ! isSameSet ( i , j ))
{
int x = findSet ( i ), y = findSet ( j );
if ( rank [ x ] > rank [ y ]) p [ y ] = x ;
else
{
p [ x ] = y ;
if ( rank [ x ] == rank [ y ]) rank [ y ] ++ ;
}
}
}
};
int main ()
{
ios_base :: sync_with_stdio ( false );
cin . tie ( 0 );
while ( cin >> n >> m && ( n != 0 || m != 0 ))
{
EdgeList . clear ();
edges_set . clear ();
for ( int i = 0 ; i < m ; i ++ )
{
int u , v , w ;
cin >> u >> v >> w ;
EdgeList . push_back ( make_pair ( w , make_pair ( u , v )));
edges_set . insert ( w );
}
sort ( EdgeList . begin (), EdgeList . end ());
UnionFind UF ( n );
for ( int i = 0 ; i < m ; i ++ )
{
auto front = EdgeList [ i ];
if ( ! UF . isSameSet ( front . second . first , front . second . second ))
{
edges_set . erase ( edges_set . find ( front . first ));
UF . unionSet ( front . second . first , front . second . second );
}
}
if ( edges_set . empty ())
cout << "forest" ;
else
{
for ( auto i = edges_set . begin (); i != prev ( edges_set . end ()); i ++ )
cout << * i << " " ;
cout << * prev ( edges_set . end ());
}
cout << endl ;
}
}
Python3.5 code below
class UnionFind :
p = rank = []
def __init__ ( self , N ):
self . p = [ i for i in range ( N )]
self . rank = [ 0 ] * N
def find_set ( self , i ):
if self . p [ i ] == i :
return i
else :
self . p [ i ] = self . find_set ( self . p [ i ])
return self . p [ i ]
def is_same_set ( self , i , j ):
return self . find_set ( i ) == self . find_set ( j )
def union_set ( self , i , j ):
if not self . is_same_set ( i , j ):
x = self . find_set ( i )
y = self . find_set ( j )
if self . rank [ x ] > self . rank [ y ]:
self . p [ y ] = x
else :
self . p [ x ] = y
if self . rank [ x ] == self . rank [ y ]:
self . rank [ y ] += 1
n , m = map ( int , input (). split ())
while n != 0 or m != 0 :
edge_list = []
edges_set = []
for i in range ( m ):
u , v , w = map ( int , input (). split ())
edge_list . append (( w , u , v ))
edges_set . append ( w )
edge_list . sort ( key = lambda edge : edge [ 0 ])
UF = UnionFind ( n )
for i in range ( m ):
front = edge_list [ i ]
if not UF . is_same_set ( front [ 1 ], front [ 2 ]):
edges_set . remove ( front [ 0 ])
UF . union_set ( front [ 1 ], front [ 2 ])
if not edges_set :
print ( 'forest' )
else :
edges_set . sort ()
for i in edges_set [: - 1 ]:
print ( str ( i ) + ' ' , end = '' )
print ( edges_set [ - 1 ])
n , m = map ( int , input (). split ())