Submission #1260509

#TimeUsernameProblemLanguageResultExecution timeMemory
1260509garyBosses (BOI16_bosses)C++20
100 / 100
861 ms1216 KiB
// BOI 2016 Bosses #include <bits/stdc++.h> using namespace std; #define int long long // #define GARY_DBG #define GARY_LIB #ifdef GARY_DBG #ifndef GARY_LIB #include <bits/stdc++.h> #endif // --- ANSI Color Codes --- #define RESET "\033[0m" #define RED "\033[31m" /* Red */ #define GREEN "\033[32m" /* Green */ #define YELLOW "\033[33m" /* Yellow */ #define BLUE "\033[34m" /* Blue */ #define MAGENTA "\033[35m" /* Magenta */ #define CYAN "\033[36m" /* Cyan */ // Overload for std::pair template<typename T, typename U> std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) { return os << '(' << p.first << ", " << p.second << ')'; } // For std::tuple template<typename... Ts> std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t) { os << '('; std::apply( [&os](const auto&... args) { bool first = true; ((os << (first ? "" : ", ") << args, first = false), ...); }, t); return os << ')'; } // For std::bitset template<size_t N> std::ostream& operator<<(std::ostream& os, const std::bitset<N>& b) { return os << "bitset{" << b.to_string() << "}"; } // Helper trait to detect if a type is a string template<typename T> struct is_string : std::false_type {}; template<> struct is_string<std::string> : std::true_type {}; template<> struct is_string<const char*> : std::true_type {}; template<> struct is_string<char*> : std::true_type {}; // Overload for std::stack // We pass by value to create a copy that we can pop from. template<typename T, typename Container> std::ostream& operator<<(std::ostream& os, std::stack<T, Container> s) { os << "stack{top: "; bool first = true; while (!s.empty()) { if (!first) os << ", "; first = false; os << s.top(); s.pop(); } os << '}'; return os; } // Overload for std::queue // We pass by value to create a copy that we can pop from. template<typename T, typename Container> std::ostream& operator<<(std::ostream& os, std::queue<T, Container> q) { os << "queue{front: "; bool first = true; while (!q.empty()) { if (!first) os << ", "; first = false; os << q.front(); q.pop(); } os << '}'; return os; } // Overload for std::priority_queue // We pass by value to create a copy that we can pop from. template<typename T, typename Container, typename Compare> std::ostream& operator<<(std::ostream& os, std::priority_queue<T, Container, Compare> pq) { os << "pq{top: "; bool first = true; while (!pq.empty()) { if (!first) os << ", "; first = false; os << pq.top(); pq.pop(); } os << '}'; return os; } // Overload for containers (like vector, list, set, map, and deque) excluding strings template<typename Container, typename std::enable_if<!is_string<Container>::value && !std::is_same<Container, std::string>::value && !std::is_same<Container, const char*>::value && !std::is_same<Container, char*>::value && !std::is_same<typename Container::value_type, char>::value, int>::type = 0> std::ostream& operator<<(std::ostream& os, const Container& container) { os << '{'; bool first = true; for (const auto& elem : container) { if (!first) os << ", "; first = false; os << elem; } os << '}'; return os; } // Helper to print multiple arguments (tuple unpacking trick) template<size_t Index = 0, typename... Ts> typename std::enable_if<Index == sizeof...(Ts)>::type print_tuple(const std::tuple<Ts...>&) { } template<size_t Index = 0, typename... Ts> typename std::enable_if < Index<sizeof...(Ts)>::type print_tuple(const std::tuple<Ts...>& t) { if (Index > 0) std::cerr << ", "; std::cerr << std::get<Index>(t); print_tuple<Index + 1>(t); } // Debug macro #define debug(...) \ do { \ std::cerr << MAGENTA << "[" << __FILE__ << ":" << __LINE__ << " (" << __func__ << ")]" << RESET << " -> "; \ std::cerr << "[" << #__VA_ARGS__ << "] ~> ["; \ print_tuple(std::make_tuple(__VA_ARGS__)); \ std::cerr << "]\n"; \ } while (0) #else #define debug(...) ((void)0) #endif constexpr int sizik = 5 * 1001; #define ar std::array #define pr std::pair #define vec std::vector typedef vec<vec<int>> _kra; int n; std::vector<int> kra[sizik]; int curr = 1; int visited[sizik]; int parent[sizik]; std::vector<int> kra1[sizik]; // O(n + S) void clear() { for (int i = 1; i <= n; i++) { parent[i] = 0; kra1[i].clear(); } } // O(n+S) void BFS(int v) { clear(); std::queue<ar<int, 2>> q; q.push({v, 0}); while (!q.empty()) { const auto [u, p] = q.front(); q.pop(); assert(1 <= u && u <= n); if (visited[u] == curr) continue; visited[u] = curr; parent[u] = p; kra1[p].push_back(u); for (const auto& y : kra[u]) { q.push({y, u}); } } } int total_cost = 0; int DFS(int v) { int q = 1; for (const auto& u : kra1[v]) { if (u != parent[v]) { q += DFS(u); } } total_cost += q; debug(v, q); return q; } int calc_cost(int root) { // check if good tree.. int z = 0; for (int i = 1; i <= n; i++) { z += kra1[i].size(); } if (z != n - 1) { // not tree . kamo.. co děláš? return INT64_MAX; } total_cost = 0; // dfs helper bro DFS(root); return total_cost; } void solve() { std::cin >> n; for (int i = 1; i <= n; i++) { int a; std::cin >> a; for (int j = 0; j < a; j++) { int b; std::cin >> b; // i -> b // b -> i kra[b].push_back(i); } } int ans = INT64_MAX; for (int i = 1; i <= n; i++) { curr++; BFS(i); int local_cost = calc_cost(i); ans = std::min(ans, local_cost); #ifdef GARY_DBG for (int j = 1; j <= n; j++) { // debug(i, j, kra1[j]); for (const auto& a : kra1[j]) { std::cout << j << " " << a << std::endl; } } #endif debug(i, local_cost); } std::cout << ans << std::endl; } int32_t main() { std::ios_base::sync_with_stdio(0); std::cin.tie(0); std::cout.tie(0); int t = 1; // std::cin >> t; for (; t > 0; t--) { solve(); } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...