SRM460 Div2 Hard(1000) TheCitiesAndRoadsDivTwo
試合中の正解者無し。与えられた辺を含む全域木は何通りあるかという問題。全域道(こんな用語あるのだろうか?)は何通りかと勘違いしていた。連結している街に同じ数字を割り振って、数字の異なる街に辺を追加していく。
#include <string> #include <vector> #include <algorithm> using namespace std; class TheCitiesAndRoadsDivTwo { static const int N = 9; int BT( int n, int city[N], int i ); public: int find( vector <string> map ); }; int TheCitiesAndRoadsDivTwo::find( vector <string> map ) { int n = (int)map.size(); // 連結している街に同じ数字を割り当てる int city[N]; for ( int i=0; i<n; i++ ) city[i] = i; for ( int i=0; i<n; i++ ) for ( int j=0; j<n; j++ ) for ( int k=0; k<n; k++ ) if ( map[j][k] == 'Y' && city[k] > city[j] ) city[k] = city[j]; return BT( n, city, 0 ); } // i以上の辺を追加してcityを全て連結する場合の数を返す int TheCitiesAndRoadsDivTwo::BT( int n, int city[N], int i ) { // 全ての街が連結されているか調べる if ( count( city, city+n, city[0] ) == n ) return 1; // 数字が異なる街を繋ぐ辺を追加 int r = 0; for ( ; i<n*n; i++ ) { int f = i%n; int t = i/n; if ( f < t && city[f] != city[t] ) { int c[N]; for ( int j=0; j<n; j++ ) c[j] = city[j]==city[t] ? city[f] : city[j]; r += BT( n, c, i+1 ); } } return r; }