062d1ffb7c 2016-03-28 kinaba: #include <iostream> 062d1ffb7c 2016-03-28 kinaba: #include <sstream> 062d1ffb7c 2016-03-28 kinaba: #include <iomanip> 062d1ffb7c 2016-03-28 kinaba: #include <vector> 062d1ffb7c 2016-03-28 kinaba: #include <string> 062d1ffb7c 2016-03-28 kinaba: #include <map> 062d1ffb7c 2016-03-28 kinaba: #include <set> 062d1ffb7c 2016-03-28 kinaba: #include <algorithm> 062d1ffb7c 2016-03-28 kinaba: #include <numeric> 062d1ffb7c 2016-03-28 kinaba: #include <iterator> 062d1ffb7c 2016-03-28 kinaba: #include <functional> 062d1ffb7c 2016-03-28 kinaba: #include <complex> 062d1ffb7c 2016-03-28 kinaba: #include <queue> 062d1ffb7c 2016-03-28 kinaba: #include <stack> 062d1ffb7c 2016-03-28 kinaba: #include <cmath> 062d1ffb7c 2016-03-28 kinaba: #include <cassert> 062d1ffb7c 2016-03-28 kinaba: #include <tuple> 062d1ffb7c 2016-03-28 kinaba: using namespace std; 062d1ffb7c 2016-03-28 kinaba: typedef long long LL; 062d1ffb7c 2016-03-28 kinaba: typedef complex<double> CMP; 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: set<int> detect_cycle(int N, const vector<vector<int>>& G) 062d1ffb7c 2016-03-28 kinaba: { 062d1ffb7c 2016-03-28 kinaba: vector<int> stk; 062d1ffb7c 2016-03-28 kinaba: set<int> cycle; 062d1ffb7c 2016-03-28 kinaba: function<void(int,int)> rec = [&](int pre, int v) { 062d1ffb7c 2016-03-28 kinaba: stk.push_back(v); 062d1ffb7c 2016-03-28 kinaba: for(int u: G[v]) if(u != pre) { 062d1ffb7c 2016-03-28 kinaba: auto it = find(stk.begin(), stk.end(), u); 062d1ffb7c 2016-03-28 kinaba: if(it == stk.end()) { 062d1ffb7c 2016-03-28 kinaba: rec(v, u); 062d1ffb7c 2016-03-28 kinaba: } else { 062d1ffb7c 2016-03-28 kinaba: cycle = set<int>(it, stk.end()); 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: stk.pop_back(); 062d1ffb7c 2016-03-28 kinaba: }; 062d1ffb7c 2016-03-28 kinaba: rec(-1, 0); 062d1ffb7c 2016-03-28 kinaba: return cycle; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: vector<vector<int>> flatten(const vector<set<int>>& GS) 062d1ffb7c 2016-03-28 kinaba: { 062d1ffb7c 2016-03-28 kinaba: vector<vector<int>> G; 062d1ffb7c 2016-03-28 kinaba: for(const auto& s: GS) 062d1ffb7c 2016-03-28 kinaba: G.emplace_back(s.begin(), s.end()); 062d1ffb7c 2016-03-28 kinaba: return G; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: class SuccessfulMerger { public: 062d1ffb7c 2016-03-28 kinaba: int minimumMergers(vector <int> road) 062d1ffb7c 2016-03-28 kinaba: { 062d1ffb7c 2016-03-28 kinaba: const int N = road.size(); 062d1ffb7c 2016-03-28 kinaba: vector<set<int>> Gs(N); 062d1ffb7c 2016-03-28 kinaba: for(int i=0; i<N; ++i) { 062d1ffb7c 2016-03-28 kinaba: Gs[i].insert(road[i]); 062d1ffb7c 2016-03-28 kinaba: Gs[road[i]].insert(i); 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: vector<vector<int>> G = flatten(Gs); 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: set<int> cy = detect_cycle(N, G); 062d1ffb7c 2016-03-28 kinaba: if(cy.empty()) 062d1ffb7c 2016-03-28 kinaba: return solve(N, G); 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: int best = N-1; 062d1ffb7c 2016-03-28 kinaba: set<int> cyl = cy; 062d1ffb7c 2016-03-28 kinaba: for(int survive: cyl) { 062d1ffb7c 2016-03-28 kinaba: cy.erase(survive); 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: map<int,int> remap; 062d1ffb7c 2016-03-28 kinaba: int XN = N - cy.size() + 1; 062d1ffb7c 2016-03-28 kinaba: for(int v=0; v<N; ++v) { 062d1ffb7c 2016-03-28 kinaba: if(cy.count(v)) { 062d1ffb7c 2016-03-28 kinaba: remap[v] = XN - 1; 062d1ffb7c 2016-03-28 kinaba: } else { 062d1ffb7c 2016-03-28 kinaba: int idx = 0; 062d1ffb7c 2016-03-28 kinaba: for(int u=0; u<v; ++u) 062d1ffb7c 2016-03-28 kinaba: if(!cy.count(u)) 062d1ffb7c 2016-03-28 kinaba: ++idx; 062d1ffb7c 2016-03-28 kinaba: remap[v] = idx; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: vector<set<int>> XGs(XN); 062d1ffb7c 2016-03-28 kinaba: for(int i=0; i<N; ++i) { 062d1ffb7c 2016-03-28 kinaba: int a = remap[i]; 062d1ffb7c 2016-03-28 kinaba: int b = remap[road[i]]; 062d1ffb7c 2016-03-28 kinaba: if(a != b) { 062d1ffb7c 2016-03-28 kinaba: XGs[a].insert(b); 062d1ffb7c 2016-03-28 kinaba: XGs[b].insert(a); 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: vector<vector<int>> XG = flatten(XGs); 062d1ffb7c 2016-03-28 kinaba: best = min<int>(best, solve(XN, XG) + cy.size() - 1); 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: cy.insert(survive); 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: return best; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: int solve(int N, const vector<vector<int>>& G) { 062d1ffb7c 2016-03-28 kinaba: if(N <= 2) 062d1ffb7c 2016-03-28 kinaba: return 0; 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: int best = N-1; 062d1ffb7c 2016-03-28 kinaba: for(int root=0; root<N; ++root) 062d1ffb7c 2016-03-28 kinaba: best = min(best, solve(N, root, G)); 062d1ffb7c 2016-03-28 kinaba: return best; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: int solve(int N, int root, const vector<vector<int>>& G) 062d1ffb7c 2016-03-28 kinaba: { 062d1ffb7c 2016-03-28 kinaba: function<int(int,int)> non_leaf_cnt = [&](int pre, int v) { 062d1ffb7c 2016-03-28 kinaba: if(G[v].size() == 1) 062d1ffb7c 2016-03-28 kinaba: return 0; 062d1ffb7c 2016-03-28 kinaba: int sum = 1; 062d1ffb7c 2016-03-28 kinaba: for(int u: G[v]) if(u != pre) 062d1ffb7c 2016-03-28 kinaba: sum += non_leaf_cnt(v, u); 062d1ffb7c 2016-03-28 kinaba: return sum; 062d1ffb7c 2016-03-28 kinaba: }; 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: int total = 0; 062d1ffb7c 2016-03-28 kinaba: for(int ch: G[root]) 062d1ffb7c 2016-03-28 kinaba: total += non_leaf_cnt(root, ch); 062d1ffb7c 2016-03-28 kinaba: return total; 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: }; 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: // BEGIN CUT HERE 062d1ffb7c 2016-03-28 kinaba: #include <ctime> 062d1ffb7c 2016-03-28 kinaba: double start_time; string timer() 062d1ffb7c 2016-03-28 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 062d1ffb7c 2016-03-28 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 062d1ffb7c 2016-03-28 kinaba: { os << "{ "; 062d1ffb7c 2016-03-28 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 062d1ffb7c 2016-03-28 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 062d1ffb7c 2016-03-28 kinaba: void verify_case(const int& Expected, const int& Received) { 062d1ffb7c 2016-03-28 kinaba: bool ok = (Expected == Received); 062d1ffb7c 2016-03-28 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 062d1ffb7c 2016-03-28 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 062d1ffb7c 2016-03-28 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 062d1ffb7c 2016-03-28 kinaba: #define END verify_case(_, SuccessfulMerger().minimumMergers(road));} 062d1ffb7c 2016-03-28 kinaba: int main(){ 062d1ffb7c 2016-03-28 kinaba: 062d1ffb7c 2016-03-28 kinaba: CASE(0) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {2, 2, 1, 1, 1}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 1; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(1) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {3, 4, 5, 4, 5, 3}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 2; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(2) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {1, 0, 1, 0, 0, 0, 1, 0, 1, 1}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 1; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(3) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {1, 2, 3, 0}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 2; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(4) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {31, 19, 0, 15, 30, 32, 15, 24, 0, 20, 40, 1, 22, 21, 39, 28, 0, 23, 15, 5, 19, 22, 6, 32, 8, 38, 35, 30, 4, 28, 32, 18, 18, 9, 22, 41, 20, 18, 6, 25, 41, 34, 4}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 25; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(5) 062d1ffb7c 2016-03-28 kinaba: int road_[] = {1, 0}; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = 0; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: /* 062d1ffb7c 2016-03-28 kinaba: CASE(6) 062d1ffb7c 2016-03-28 kinaba: int road_[] = ; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = ; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: CASE(7) 062d1ffb7c 2016-03-28 kinaba: int road_[] = ; 062d1ffb7c 2016-03-28 kinaba: vector <int> road(road_, road_+sizeof(road_)/sizeof(*road_)); 062d1ffb7c 2016-03-28 kinaba: int _ = ; 062d1ffb7c 2016-03-28 kinaba: END 062d1ffb7c 2016-03-28 kinaba: */ 062d1ffb7c 2016-03-28 kinaba: } 062d1ffb7c 2016-03-28 kinaba: // END CUT HERE