문제
목표량
- 시간 제한: 1초
정점 N개의 트리에서 두 사람이 게임을 진행하려 한다.
각 정점은 1번부터 N번 까지 번호가 매겨져 있고 루트노드는 1번 노드이다.
게임은 서로 턴을 번갈아 가며 진행되고 트리 위에 놓을 수 있는 말과 함께 진행된다.
두 사람의 점수는 모두 0점으로 시작한다.
각 턴마다 두 사람은 다음과 같은 작업을 반복한다.
현재 말이 놓여 있는 정점의 번호만큼 자신의 점수에 더한다.
현재 말이 놓여 있는 정점의 자식 정점이 없다면 그대로 게임을 종료한다.
자식 정점이 존재한다면 자식 정점 중 원하는 자식 정점으로 말을 옮긴다.
게임이 종료되었을 때 선공의 점수가 후공의 점수보다 높거나 같다면 선공이 승리하고 아니라면 후공이 승리한다.
두 사람이 최적으로 플레이할 때, 처음 말이 놓여져 있는 정점의 번호에 따라 선공이 이기는지 후공이 이기는지 구해보자.
지시사항
입력
- 첫째 줄에 정점의 수 N이 주어진다.
1≤ N ≤100000
1 ≤ m ≤ 500
- 둘째 줄부터 N−1개의 줄에 간선을 나타내는 정수 u,v가 주어진다.
1 ≤ u, v ≤ n
- 둘째 줄부터 N−1개의 줄에 간선을 나타내는 정수 u,v가 주어진다.
출력
- N개의 줄에 걸쳐 정답을 출력한다.
- i번째 줄에는 말의 시작위치가 i번 정점일 때의 결과를 출력한다.
- 선공이 이긴다면 1을 후공이 이긴다면 0을 출력한다.
입력 예시
5
1 3
2 1
3 4
5 1
출력 예시
1
1
0
1
1
풀이
접근
- 작성중-
풀이
- 작성
- 작성
코드
더보기
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;
vector<vector<int>> A;
vector<int> Score;
vector<bool> visited;
queue<int> Q;
stack<int> S;
void BFS(int start);
void Check(void);
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
A.resize(N + 1);
Score.resize(N + 1);
visited.resize(N + 1);
for (int i = 0; i < N - 1; ++i) {
int u, v;
cin >> u >> v;
A[u].push_back(v);
A[v].push_back(u);
}
BFS(1);
visited = vector<bool>(N + 1, false);
Check();
for (int i = 1; i <= N; ++i)
cout << (Score[i] >= 0 ? 1 : 0) << '\n';
return 0;
}
void BFS(int start)
{
Q.push(start);
visited[start] = true;
while (!Q.empty())
{
int node = Q.front();
Q.pop();
S.push(node);
for (int i : A[node])
{
if (!visited[i])
{
visited[i] = true;
Q.push(i);
}
}
}
}
void Check(void)
{
while (!S.empty())
{
int node = S.top();
S.pop();
visited[node] = true;
bool IsLeafNode = true;
int MinValue = INT_MAX;
for (int child : A[node]) {
if (visited[child]) {
IsLeafNode = false;
MinValue = min(MinValue, Score[child]);
}
}
Score[node] = (IsLeafNode ? node : (node - MinValue));
}
}
↑ 더보기 클릭으로 펼치기
모범답안
더보기
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
ll n, a, b;
vector<ll>v[100050];
ll dp[100050], inf = 1e12;
void dfs(ll x, ll par) {
ll ret = inf;
for (auto nxt : v[x]) {
if (nxt == par)continue;
dfs(nxt, x);
ret = min(ret, dp[nxt]);
}
if (ret == inf)ret = 0;
dp[x] = x - ret;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i < n; i++) {
cin >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1, 0);
for (int i = 1; i <= n; i++) {
if (dp[i] >= 0)cout << "1";
else cout << "0";
cout << '\n';
}
}
↑ 더보기 클릭으로 펼치기
후기
체감상 진짜 어려웠다.
주어진 예제 테스트 케이스만 맞다고 나오고, 제출하면 테스트 케이스가 다 틀리다고 나와서 이런 저런 방법으로 구현을
5 ~ 6개는 한 것 같다.
'공부 > PS' 카테고리의 다른 글
엘리스 코드 챌린지 예선 [Day 3] 문제풀이 (0) | 2024.07.10 |
---|---|
엘리스 코드 챌린지 예선 [Day 2] 문제풀이 (0) | 2024.07.09 |
엘리스 코드 챌린지 예선 [Day 1] 문제풀이 (0) | 2024.07.08 |
[C++] 백준 21568번 (0) | 2024.04.07 |