제출 #1096029

#제출 시각아이디문제언어결과실행 시간메모리
1096029frankmauer1812Cat in a tree (BOI17_catinatree)C++14
100 / 100
169 ms66896 KiB
#include<bits/stdc++.h> using namespace std; #define sonic ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0) #define IO(main) if(fopen(main".inp", "r")){freopen(main".inp", "r", stdin);freopen(main".out", "w", stdout);} #define ll long long #define ull unsigned long long #define pii pair<int, int> #define pll pair<long long, long long> #define fi first #define se second #define pb push_back #define eb emplace_back #define el cout << "\n" #define SZ(x) (x).size() #define ALL(x) (x).begin(), (x).end() #define BIT(x, i) (((x) >> (i)) & (1LL)) #define MASK(x) ((1LL) << (x)) #define FOR(i, a, b) for(int (i) = (a), _b = (b); (i) <= _b; (i)++) #define FORD(i, a, b) for(int (i) = (a), _b = (b); (i) >= _b; (i)--) const int N = MASK(20) + 5; const int mod = 1e9 + 7; const ll INF = 1e9 + 7; template<class X, class Y> bool maximize(X &x, Y y){if(x < y){x = y; return true;} return false;} template<class X, class Y> bool minimize(X &x, Y y){if(x > y){x = y; return true;} return false;} void add(int &x, int y){x += y; if(x >= mod) x -= mod;} void sub(int &x, int y){x -= y; if(x < 0) x += mod;} int mul(int x, int y) {return 1LL * x * y % mod;} int calPw(int x, int y){ int ans = 1; while(y){ if(y & 1) ans = 1LL * ans * x % mod; x = 1LL * x * x % mod; y >>= 1; } return ans; } ///Deruck Phung - Luong The Vinh High School For The Gifted int n, d; vector<int> adj[N]; ///Code namespace sub1{ bool check(){ return n <= 20; } pii dis[N][2]; void Solve(){ int Ans = 0; for(int mask = 0; mask < MASK(n); mask++){ for(int i = 1; i <= n; i++) dis[i][0] = dis[i][1] = {-1, -1}; queue<pii> qu; for(int i = 1; i <= n; i++) if(BIT(mask, i - 1)){ dis[i][0] = {0, i}; qu.push({i, 0}); } while(qu.size()){ int u = qu.front().fi; int type = qu.front().se; qu.pop(); for(int v : adj[u]){ if(dis[v][0].fi == -1){ dis[v][0] = dis[u][type]; dis[v][0].fi++; qu.push({v, 0}); } else if(dis[v][1].fi == -1 && dis[u][type].se != dis[v][0].se){ dis[v][1] = dis[u][type]; dis[v][1].fi++; qu.push({v, 1}); } } } bool oke = true; for(int i = 1; i <= n; i++) if(BIT(mask, i - 1)){ if(dis[i][1].fi > 0 && dis[i][1].fi < d) oke = false; } if(oke) Ans = max(Ans, __builtin_popcount(mask)); } cout << Ans; } } namespace sub2{ bool check(){ return n <= 5000; } int mx[N]; vector<int> dp[N]; vector<int> Merge(vector<int> A, vector<int> B){ vector<int> C; C.resize(min(d, max((int) A.size(), (int) B.size() + 1)), 0); for(int i = 0; i < A.size(); i++){ for(int j = max(0, d - i - 1); j < B.size(); j++){ C[min(i, j + 1)] = max(C[min(i, j + 1)], A[i] + B[j]); } } for(int i = C.size() - 1; i >= 0; i--){ if(i < C.size() - 1) C[i] = max(C[i], C[i + 1]); if(i < A.size()) C[i] = max(C[i], A[i]); if(i > 0 && i <= B.size()) C[i] = max(C[i], B[i - 1]); } return C; } void dfs(int u, int p){ dp[u].push_back(1); for(int v : adj[u]) if(v != p){ dfs(v, u); dp[u] = Merge(dp[u], dp[v]); } } void Solve(){ dfs(1, 1); int Ans = 0; for(int i = 0; i < dp[1].size(); i++) Ans = max(Ans, dp[1][i]); cout << Ans; } } namespace sub3{ int f[N], g[N], cnt[N]; void dfs(int u, int p){ ///g[u]: thằng chưa được lấy trong cây con gốc u, có dist tới đỉnh u là g[u] ///Khi đó, với mỗi u, ta sẽ tìm cách lấy g[v] sao cho mỗi thằng >= d / 2 ///Vậy khoảng cách của mỗi thằng luôn đảm bảo >= d / 2 ///Ngoài ra, giả sử có 2 đỉnh là con của v, vậy 1 là nó sẽ lấy tại v ///2 là dist của 2 thằng < d, suy ra mỗi thằng v chỉ lấy 1 thằng. ///Để tìm được nhiều nhất -> g[u] luôn lớn nhất. ///f[u]: min dist từ thằng được chọn đến u ///cnt[u]: chọn trong cây con gốc u nhưng k chọn thằng u f[u] = 1e9 + 7; g[u] = -1; for(int v : adj[u]) if(v != p){ dfs(v, u); cnt[u] += cnt[v]; f[u] = min(f[u], f[v] + 1); ///Có thể lấy thằng v if(g[v] != -1){ if(2 * (g[v] + 1) >= d){ f[u] = min(f[u], g[v] + 1); cnt[u]++; } else g[u] = max(g[u], g[v] + 1); } } ///Nếu khoảng cách của g[u] (thằng v cây con u chưa được lấy lớn nhất) ///và f[u] (thằng gần u nhất đã được chọn) < d thì coi như ta k thể lấy ///thằng đang được lưu ở g[u] if(g[u] + f[u] < d) g[u] = -1; if(g[u] == -1 && f[u] >= d) g[u] = 0; // cout << u << " " << cnt[u] << " " << g[u] << "\n"; } void Solve(){ dfs(1, 1); cout << cnt[1] + (g[1] >= 0); } } void Solve(){ } void Read(){ cin >> n >> d; for(int i = 2; i <= n; i++){ int x; cin >> x; ++x; adj[x].push_back(i); adj[i].push_back(x); } if(sub1::check()) sub1::Solve(); else if(sub2::check()) sub2::Solve(); else sub3::Solve(); } int main(){ sonic; IO("main"); int TEST = 1; while(TEST--){ Read(); Solve(); } }

컴파일 시 표준 에러 (stderr) 메시지

catinatree.cpp: In function 'std::vector<int> sub2::Merge(std::vector<int>, std::vector<int>)':
catinatree.cpp:104:26: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  104 |         for(int i = 0; i < A.size(); i++){
      |                        ~~^~~~~~~~~~
catinatree.cpp:105:46: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  105 |             for(int j = max(0, d - i - 1); j < B.size(); j++){
      |                                            ~~^~~~~~~~~~
catinatree.cpp:111:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  111 |             if(i < C.size() - 1)
      |                ~~^~~~~~~~~~~~~~
catinatree.cpp:113:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  113 |             if(i < A.size())
      |                ~~^~~~~~~~~~
catinatree.cpp:115:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  115 |             if(i > 0 && i <= B.size())
      |                         ~~^~~~~~~~~~~
catinatree.cpp: In function 'void sub2::Solve()':
catinatree.cpp:134:26: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  134 |         for(int i = 0; i < dp[1].size(); i++)
      |                        ~~^~~~~~~~~~~~~~
catinatree.cpp: In function 'int main()':
catinatree.cpp:5:52: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    5 | #define IO(main) if(fopen(main".inp", "r")){freopen(main".inp", "r", stdin);freopen(main".out", "w", stdout);}
      |                                             ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
catinatree.cpp:210:5: note: in expansion of macro 'IO'
  210 |     IO("main");
      |     ^~
catinatree.cpp:5:84: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    5 | #define IO(main) if(fopen(main".inp", "r")){freopen(main".inp", "r", stdin);freopen(main".out", "w", stdout);}
      |                                                                             ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
catinatree.cpp:210:5: note: in expansion of macro 'IO'
  210 |     IO("main");
      |     ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...