#include <bits/stdc++.h>
using namespace std;
template<typename T>
bool maximize(T& a, const T& b){
if(a < b){
return a = b, true;
} return false;
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
freopen("task.inp", "r", stdin);
freopen("task.out", "w", stdout);
#endif // LOCAL
int N, K;
cin >> N >> K;
vector<vector<int>> e(N, vector<int>(N));
for(int i = 0, j = 0; i < N; ++i){
while(cin >> j){
if(!j) break;
--j;
e[i][j] = 1;
}
}
const int inf = 1e9;
vector<vector<vector<int>>> dp(N, vector<vector<int>>(N, vector<int>(2, -inf)));
vector<vector<vector<int>>> max_dp(N, vector<vector<int>>(N, vector<int>(2, -inf)));
//dp[l][r][k] = maximum paths if we start at l, end at r and moving around range [l...r] in k-wise
//max_dp[l][r][k] = maximum paths if we start at l end at somewhere but still moving around range [l...r] in k-wise
for(int i = 0; i < N; ++i){
dp[i][i][0] = dp[i][i][1] = max_dp[i][i][0] = max_dp[i][i][1] = 0;
}
vector<vector<int>> to(2, vector<int>(N));
for(int i = 0; i < N; ++i){
to[0][i] = (i + 1) % N;
to[1][i] = (i + N - 1) % N;
}
auto solve = [&](int l, int r, int k){
if(e[l][r]){
maximize(dp[l][r][k], 1); //base-case
maximize(max_dp[l][r][k], max_dp[r][to[k][l]][k ^ 1] + 1); //case go back but not cut [l...r - 1]
}
for(int nxt = to[k][l]; nxt != r; nxt = to[k][nxt]){
if(e[l][nxt]){
maximize(dp[l][r][k], dp[l][nxt][k] + dp[nxt][r][k]);
maximize(max_dp[l][r][k], dp[l][nxt][k] + max_dp[nxt][r][k]);
}
}
maximize(max_dp[l][r][k], max_dp[l][to[k ^ 1][r]][k]);
};
for(int len = 1; len < N; ++len){
for(int l = 0, r = len; l < N; ++l, r = (r + 1) % N){
solve(l, r, 0);
solve(r, l, 1);
}
}
pair<int, int> res = {0, 0};
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
for(int k = 0; k < 2; ++k){
maximize(res, make_pair(max_dp[i][j][k], i));
}
}
}
if(!K){
cout << res.first << ' ' << res.second + 1 << '\n';
return 0;
}
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
for(int k = 0; k < 2; ++k){
if(dp[i][j][k] <= 0) continue;
int bestS = to[k][j];
while(bestS != i && !e[bestS][i]) bestS = to[k][bestS];
if(bestS == i) continue;
//just consider the first pos that in range [j+1...N-1] u [0...i - 1] that have edge with e[pos][i]
//because when we move the j up, the range [i...j] will be extended and the max_dp[i][j][k] <= max_dp[i][to[k][j]][k]
for(int candidate = to[k][bestS]; candidate != i; candidate = to[k][candidate]){ //choose the T
if(e[j][candidate]){ //S -> i -> ... -> j -> T -> ...
int last = max(max_dp[candidate][to[k][bestS]][k ^ 1], max_dp[candidate][to[k ^ 1][i]][k]); //some last paths
int solution = 1 + dp[i][j][k] + 1 + last;
maximize(res, {solution, bestS});
}
}
}
}
}
cout << res.first << ' ' << res.second + 1 << '\n';
return 0;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
336 KB |
Output is correct |
2 |
Correct |
1 ms |
336 KB |
Output is correct |
3 |
Correct |
1 ms |
336 KB |
Output is correct |
4 |
Correct |
1 ms |
592 KB |
Output is correct |
5 |
Correct |
2 ms |
592 KB |
Output is correct |
6 |
Correct |
3 ms |
848 KB |
Output is correct |
7 |
Correct |
4 ms |
848 KB |
Output is correct |
8 |
Correct |
5 ms |
1104 KB |
Output is correct |
9 |
Correct |
6 ms |
1388 KB |
Output is correct |
10 |
Correct |
8 ms |
1616 KB |
Output is correct |
11 |
Correct |
8 ms |
1616 KB |
Output is correct |
12 |
Correct |
67 ms |
4944 KB |
Output is correct |
13 |
Correct |
178 ms |
10576 KB |
Output is correct |
14 |
Correct |
296 ms |
18512 KB |
Output is correct |
15 |
Correct |
1055 ms |
28920 KB |
Output is correct |
16 |
Correct |
1244 ms |
28912 KB |
Output is correct |
17 |
Correct |
1071 ms |
28908 KB |
Output is correct |
18 |
Correct |
571 ms |
28912 KB |
Output is correct |
19 |
Correct |
1497 ms |
28916 KB |
Output is correct |
20 |
Correct |
1416 ms |
28904 KB |
Output is correct |