Machineboy空
1325 : 효율적인 해킹 - dfs, 인접리스트, 정렬 본문
https://www.acmicpc.net/problem/1325
1325번: 효율적인 해킹
첫째 줄에, N과 M이 들어온다. N은 10,000보다 작거나 같은 자연수, M은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에 신뢰하는 관계가 A B와 같은 형식으로 들어오며, "A가 B를 신뢰한
www.acmicpc.net
문제요약
컴퓨터 간 신뢰 관계를 참고하여 최대한 해킹할 수 있는 컴퓨터의 번호를 출력
난이도
Silver 1
풀이 포인트
- DFS
- 항상 초기화 타이밍을 잘 맞춰줘야 함.
- 인접리스트
- 컴퓨터 간 신뢰관계 인접리스트로 표현
- sort
//내림차순 정렬
sort(ret.begin(), ret.end(), greater<pair<int, int>>());
REVIEW
dfs문제는 이제 좀 익숙해진 것 같다.
모범 풀이 접근에서 배워야할 것은
#시간복잡도 어림짐작 하고 들어가는 습관
우선은 풀기 급급하기 때문에, 시간복잡도는 고려하지 않고 코드부터 짜기 시작하는데,
이 문제 같은 경우에도 최대 범위가 1만이므로 dfs로 모든 정점을 탐색한다 가정 하에, 최악의 시간복잡도가 O(n^2)이 되므로
계산횟수가 1억이 되어버리는 꽤나 시간복잡도가 높은 문제이기 때문에
다른 풀이가 없을지 한번쯤은 생각해보고 들어갔어야 했다.
#공간복잡도 : 최소한의 공간으로 효율적 활용
난 생각하기가 편하게끔 하나면 되는 저장 배열이나 벡터 공간을 너무 많이 마련하는 경향이 있는데,
이건 노하우가 좀 쌓여야할 듯.
# 최대 최소 갱신 그때그때 하는 것
나는 또 sort를 해주어 가장 마지막 값에 접근하는 식으로 했는데, 그때 그때 갱신하기.
# 초기화
정말 바보같은 실수이긴 한데,
디버깅을 한다고 hackdfs함수를 한번 돌리고, 정작 정답내기 위해 필요한 값에 할당할 함수를 한 번 더 돌려버렸다.
무슨 말이냐면, 방문배열을 초기화하지 않고서 디버깅 코드에 진짜 값을 넣어버리고 정작 필요한 코드엔 이상한 값을 넣어버리고 있었던 것..
항상 테스트 케이스가 여러개이기 때문에 초기화의 타이밍을 잘 체크할 것!
그래도 한번에 정답을 받아 짜릿했다..

CODE
#include <bits/stdc++.h>
using namespace std;
int n, m, u, v;
vector<pair<int, int>> ret;
vector<int> computerN;
vector<int> adj[10004];
bool visited[10004];
int hack(int node)
{
int cnt = 1;
visited[node] = true;
for (int i = 0; i < adj[node].size(); i++)
{
if (visited[adj[node][i]])
continue;
cnt += hack(adj[node][i]);
}
return cnt;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
cin >> v >> u;
adj[u].push_back(v);
}
for (int i = 1; i <= n; i++)
{
// 초기화 잘 해주기
memset(visited, false, sizeof(visited));
if (!visited[i])
{
int k = hack(i); //무슨 차이지, 한번 돌리면 memset안되니까 결과가 다르지.
//cout << "현재 방문 노드는 " << i << '\n';
//cout << "방문 노드로 부터 해킹한 컴퓨터는 " << k << "대\n";
ret.push_back({k, i});
}
}
for(int i = 0; i < ret.size(); i++){
//cout << ret[i].first << "," << ret[i].second<<'\n';
}
// ret<해킹가능한 컴퓨터 대수, 컴퓨터 번호>
sort(ret.begin(), ret.end(), greater<pair<int, int>>());
for (int i = 0; i < ret.size(); i++)
{
//cout <<"정렬 후 \n";
//cout << ret[i].first << "," << ret[i].second << '\n';
}
int max_hack_cnt = ret[0].first;//여기가 4가 되어야 해..
//cout << "해킹할 수 있는 최대 컴퓨터는 " << max_hack_cnt <<'\n';
for (int i = 0; i <ret.size() ; i++)
{
if (ret[i].first == max_hack_cnt)
{
//cout << ret[i].first <<"대 해킹할 수 있는 컴퓨터의 번호는 " << ret[i].second <<'\n';
computerN.push_back(ret[i].second);
}
}
sort(computerN.begin(), computerN.end());
for (int a : computerN)
cout << a << " ";
return 0;
}
#include <bits/stdc++.h>
using namespace std;
vector<int> v[10001];
int dp[10001], mx, visited[10001], n, m, a, b;
int dfs(int here)
{
visited[here] = 1;
int ret = 1;
for (int there : v[here])
{
if (visited[there])
continue;
ret += dfs(there);
}
return ret;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
while (m--)
{
cin >> a >> b;
v[b].push_back(a);
}
for (int i = 1; i <= n; i++)
{
memset(visited, 0, sizeof(visited));
dp[i] = dfs(i);
mx = max(dp[i], mx);
}
for (int i = 1; i <= n; i++)
if (mx == dp[i])
cout << i << " ";
return 0;
}
'Computer > Coding Test' 카테고리의 다른 글
14502 : 연구소 - DFS, deep copy (0) | 2024.02.20 |
---|---|
2852 : NBA 농구 - substr, prev, temp (0) | 2024.02.20 |
17298 : 오큰수 - stack, 짝짓기 (1) | 2024.02.19 |
9012 : 괄호 - stack, 그리디 알고리즘, getline(cin,s) (0) | 2024.02.16 |
1436 : 영화감독 숌 - 숫자, 문자 변환 / 브루트 포스 (0) | 2024.02.16 |