1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <utility>
using namespace std;
//==========================================================
int subtreeSize( int i, int parent, const vector< vector<int> > &graph, map<pair<int,int>,int> &memo )
{
if ( parent >= 0 )
{
auto it = memo.find( {i,parent} );
if ( it != memo.end() ) return it->second; // Computed before, so no need to recurse
}
int sum = 1;
for ( int j : graph[i] )
{
if ( j != parent ) sum += subtreeSize( j, i, graph, memo ); // Recurse through children
}
memo[{i,parent}] = sum; // Store value in case needed again
return sum;
}
//==========================================================
int main()
{
istringstream in();
int n;
cin >> n;
vector< vector<int> > graph( n ); // Connectors for each node
for ( int i = 1; i < n; i++ ) // Tree has n-1 edges
{
int a, b;
cin >> a >> b;
graph[a].push_back( b );
graph[b].push_back( a );
}
// For each node, find maximal count amongst its proper subtrees
vector<int> subcount( n, 0 );
map<pair<int,int>,int> memo; // Allow for memoisation
for ( int i = 0; i < n; i++ )
{
for ( int j : graph[i] ) subcount[i] = max( subcount[i], subtreeSize( j, i, graph, memo ) );
}
// Minimise subtree count
int minimum = *min_element( subcount.begin(), subcount.end() );
for ( int i = 0; i < n; i++ ) if ( subcount[i] == minimum ) cout << i << ' ';
cout << '\n';
}
|