Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#define ONLINE_JUDGE
- #if defined(ONLINE_JUDGE)
- #define _SECURE_SCL 0
- #endif
- #include <iostream>
- #include <iomanip>
- #include <string>
- #include <sstream>
- #include <fstream>
- #include <algorithm>
- #include <vector>
- #include <deque>
- #include <set>
- #include <map>
- #include <functional>
- #include <memory>
- #include <cmath>
- #include <climits>
- #include <numeric>
- #include <tuple>
- #include <random>
- #include <memory.h>
- #include <stdint.h>
- #if !defined(__GNUC__)
- #else // !defined(__GNUC__)
- #define _CrtDbgBreak() __builtin_trap()
- #endif // !defined(__GNUC__)
- #if defined(ONLINE_JUDGE)
- #define LOCAL_TEST 0
- #else
- #define LOCAL_TEST 1
- #endif
- template<typename T1, typename T2> auto Endl(std::basic_ostream<T1, T2>& ostr) -> decltype(std::endl<T1, T2>(ostr)) {
- return std::endl<T1, T2>(ostr);
- }
- #if LOCAL_TEST
- struct AssertsCounter
- {
- AssertsCounter(): counter(0) {}
- ~AssertsCounter() { std::cerr << Endl << "DIAG: " << (counter == 0 ? "OK" : "FAIL!!!") << " Asserts count: " << counter << Endl; }
- void Increment() { counter++; }
- uint32_t counter;
- };
- AssertsCounter g_assertsCounter;
- #define LOCAL_ASSERT(expr) { if (!(expr)) {std::cerr << "ASSERT FAILED (" << __LINE__ << "): '" << #expr << "'" << Endl; g_assertsCounter.Increment(); _CrtDbgBreak(); } }
- #define LOCAL_ASSERT_EQ(expr1, expr2) { if ((expr1) != (expr2)) {std::cerr << "ASSERT FAILED (" << __LINE__ << "): '" << #expr1 << "' == '" << #expr2 << "' (" << (expr1) << " vs " << (expr2) << "')" << Endl; g_assertsCounter.Increment(); _CrtDbgBreak(); } }
- #else
- volatile bool isLocalTestEnabled = 0;
- #define LOCAL_ASSERT(expr)
- #define LOCAL_ASSERT_EQ(expr1, expr2)
- #endif
- bool g_isLocalPrintEnabled = (bool)(LOCAL_TEST);
- #define LOCAL_PRINT() if (!g_isLocalPrintEnabled) { } else std::cerr // << .. << ..
- typedef std::string string8_t;
- typedef long double ld_t;
- typedef std::vector<size_t> vector_size_t;
- typedef std::vector<uint8_t> vector_uint8_t;
- typedef std::vector<int32_t> vector_int32_t;
- typedef std::vector<uint32_t> vector_uint32_t;
- typedef std::vector<int64_t> vector_int64_t;
- typedef std::vector<uint64_t> vector_uint64_t;
- typedef std::vector<string8_t> vector_string8_t;
- typedef std::vector<vector_size_t> vector_2d_size_t;
- typedef std::vector<vector_int32_t> vector_2d_int32_t;
- typedef std::vector<vector_uint32_t> vector_2d_uint32_t;
- typedef std::vector<vector_int64_t> vector_2d_int64_t;
- typedef std::vector<vector_uint64_t> vector_2d_uint64_t;
- typedef std::set<size_t> set_size_t;
- typedef std::set<int32_t> set_int32_t;
- typedef std::set<uint32_t> set_uint32_t;
- typedef std::set<int64_t> set_int64_t;
- typedef std::set<uint64_t> set_uint64_t;
- typedef std::set<string8_t> set_string8_t;
- typedef std::multiset<size_t> multiset_size_t;
- typedef std::multiset<string8_t> multiset_string8_t;
- // Auxiliary functions definition
- //
- template<typename T> void UpdateMin(T& a, const T b) {a = std::min(a, b);}
- template<typename T> void UpdateMax(T& a, const T b) {a = std::max(a, b);}
- const ld_t Pi = std::atan(1.0L) * 4.0L;
- static const ld_t Eps = 1.0e-09;
- template<typename T> bool IsEqual(const T a, const T b) { return std::abs(a - b) < Eps; }
- template<typename T> bool IsGreater(const T a, const T b) { return a > b + Eps; }
- template<typename T> bool IsLess(const T a, const T b) { return a + Eps < b; }
- template<typename T> bool IsGreaterEqual(const T a, const T b) { return !IsLess(a, b); }
- template<typename T> bool IsLessEqual(const T a, const T b) { return !IsGreater(a, b); }
- template<typename T> string8_t ToStr(const T& val) { std::ostringstream ostr; ostr << val; return ostr.str(); }
- template<typename T> bool FromStr(const string8_t& str, T& val) {std::istringstream istr(str); istr >> val; return !!istr; }
- template<typename T> T FromStr(const string8_t& str) {T val = {}; std::istringstream istr(str); istr >> val; return val; }
- template<typename ContainerType, typename ValueType> bool Contains(const ContainerType& c, const ValueType& v) { return c.find(v) != c.end(); }
- uint64_t SafeAdd(uint64_t a, uint64_t b) { uint64_t M = std::numeric_limits<uint64_t>::max(); return a <= M - b ? a + b : M; }
- uint64_t SafeMul(uint64_t a, uint64_t b) { uint64_t M = std::numeric_limits<uint64_t>::max(); return a <= M / b ? a * b : M; }
- template<typename T> std::istream& operator>>(std::istream& ist, std::vector<T>& data)
- {
- LOCAL_ASSERT(!!ist);
- for (size_t i = 0; i < data.size(); i++) { ist >> data[i]; }
- return ist;
- }
- template<typename T> T Read(std::istream& ist)
- {
- LOCAL_ASSERT(!!ist);
- T val; ist >> val; return val;
- }
- template<typename T> std::ostream& operator<<(std::ostream& ost, const std::vector<T>& data)
- {
- for (size_t i = 0; i < data.size(); i++) { if (i != 0) { ost << ' '; } ost << data[i]; }
- return ost;
- }
- #if defined(ONLINE_JUDGE)
- template<size_t id> class StopWatch { };
- #else
- #include <library/lib_stopwatch.h>
- #include <library/lib_random.h>
- library::random::Rand g_rnd;
- #endif
- void Wave(const vector_2d_size_t& links, const size_t start, vector_size_t& distances) {
- vector_size_t isVisited(links.size());
- size_t currentDistance = 0;
- isVisited[start] = 1;
- distances[start] = 0;
- std::deque<size_t> q;
- q.emplace_back(start);
- while (!q.empty()) {
- currentDistance += 1;
- std::deque<size_t> nq;
- for (const auto qi : q) {
- for (const auto v : links[qi]) {
- if (!isVisited[v]) {
- nq.emplace_back(v);
- isVisited[v] = 1;
- distances[v] = currentDistance;
- }
- }
- }
- q.swap(nq);
- }
- }
- bool IsAmbigous(const vector_2d_size_t& links, const size_t v, const vector_size_t& distances) {
- size_t minDistance = std::numeric_limits<size_t>::max();
- size_t minCount = 0;
- for (size_t vi : links[v]) {
- if (distances[vi] < minDistance) {
- minDistance = distances[vi];
- minCount = 1;
- } else if (distances[vi] == minDistance) {
- minCount += 1;
- }
- }
- if (minCount == 0) {
- return false;
- }
- return minCount != 1;
- }
- bool Solve(std::istream& ist, std::ostream& ost, const bool multipleTestMode)
- {
- StopWatch<1> sw; (void)sw;
- //
- size_t n, m;
- ist >> n >> m;
- if (multipleTestMode && !ist)
- return false;
- //
- LOCAL_PRINT() << Endl << "Next test" << Endl;
- vector_2d_size_t flinks(n);
- vector_2d_size_t rlinks(n);
- for (size_t i = 0; i < m; i++) {
- size_t u, v;
- ist >> u >> v;
- --u; --v;
- rlinks[v].emplace_back(u);
- flinks[u].emplace_back(v);
- }
- size_t k;
- ist >> k;
- vector_size_t p(k);
- for (size_t i = 0; i < k; i++) {
- ist >> p[i];
- --p[i];
- }
- const size_t end = p[p.size() - 1];
- vector_size_t distances(n);
- Wave(rlinks, end, distances);
- vector_size_t isAmbigous(n);
- for (size_t i = 0; i < n; i++) {
- isAmbigous[i] = IsAmbigous(flinks, i, distances);
- }
- isAmbigous[end] = 0;
- size_t minCount = 0;
- size_t maxCount = 0;
- for (size_t i = 0; i < k; i++) {
- const size_t v = p[i];
- const size_t currMinDistance = distances[v];
- bool canRebuild = false;
- bool mustRebuild = false;
- if (isAmbigous[v]) {
- canRebuild = true;
- } else if (i + 1 < k) {
- const size_t nextMinDistance = distances[p[i + 1]];
- if (nextMinDistance >= currMinDistance) {
- canRebuild = true;
- mustRebuild = true;
- }
- }
- if (canRebuild) {
- maxCount += 1;
- }
- if (mustRebuild) {
- minCount += 1;
- }
- }
- ost << minCount << " " << maxCount << Endl;
- LOCAL_ASSERT(minCount <= maxCount);
- return multipleTestMode;
- }
- #if LOCAL_TEST
- void Test()
- {
- using namespace library::random;
- //const auto genVector = GenFactory::CreateGenVector(GenRange<size_t>(2, 10), GenRange<int32_t>(-100, +200));
- for (size_t t = 0; t < 10; t++)
- {
- //const vector_int32_t data = genVector();
- //size_t ans = GetAns(data);
- //size_t ref = GetAnsRef(data);
- //LOCAL_ASSERT_EQ(ref, ans);
- }
- }
- #endif
- void RunSolve(std::istream& ist, std::ostream& ost)
- {
- #if !defined(ONLINE_JUDGE)
- while(Solve(ist, ost, true)) {};
- #else
- Solve(ist, ost, false);
- #endif
- }
- int main(int argc, const char *argv[])
- {
- #if !defined(ONLINE_JUDGE)
- Test();
- #endif
- std::ios_base::sync_with_stdio(false);
- if (argc > 1)
- {
- std::ifstream ifs(argv[1]);
- if (!ifs)
- {
- std::cout << "File not found: " << argv[1] << Endl;
- return 1;
- }
- RunSolve(ifs, std::cout);
- return 0;
- }
- RunSolve(std::cin, std::cout);
- }
Advertisement
Add Comment
Please, Sign In to add comment