백준 3977번 축구 전술
사용한 알고리즘 : SCC
문제는 각 점들을 SCC로 묶었을 때, indegree가 0인 (들어오는 edge가 없는) SCC가 딱 1개 있는지 여부였습니다. (2개 있다면 서로는 서로에게 못가니, 한 지점에서 다른 모든 지점으로 갈 수 있는지 묻는 물음에 부합하지 못합니다.)
우선 각 점들을 SCC로 묶었습니다.
이후 모든 점들을 돌면서, 그 점의 자식이 자신과 다른 SCC 에 있는지 확인하고,
만약 다른 SCC에 있는 경우, 자식이 속한 SCC의 indegree++ 해주었습니다.
이후 SCC를 모아놓은 벡터를 돌며 indegree가 0 인 SCC가 1개인지 확인 후,
1개인 경우 답을 말하고,
아닌 경우 "Confused"를 외쳐주었습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
const int MAX = 100001; | |
int T, N, M, cnt, SN, check, sn[MAX], dfsn[MAX], indegree[MAX]; | |
vector<int> adj[MAX]; | |
bool finished[MAX]; | |
bool visited[MAX]; | |
stack<int> S; | |
vector<vector<int>> SCC; | |
int DFS(int curr){ | |
dfsn[curr] = ++cnt; | |
S.push(curr); | |
int result = dfsn[curr]; | |
for (int next: adj[curr]){ | |
if(dfsn[next] == 0) result = min(result, DFS(next)); | |
else if(!finished[next]) result = min(result, dfsn[next]); | |
} | |
if(result == dfsn[curr]){ | |
vector<int> currSCC; | |
while(1){ | |
int t = S.top(); | |
S.pop(); | |
currSCC.push_back(t); | |
finished[t] = true; | |
sn[t] = SN; | |
if(t==curr) break; | |
} | |
SCC.push_back(currSCC); | |
SN++; | |
} | |
return result; | |
} | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> T; | |
while(T--){ | |
cin >> N >> M; | |
bool flag = false; | |
check = -1; | |
cnt = 0; | |
SCC.clear(); | |
SN = 0; | |
while(!S.empty()) S.pop(); | |
for (int i = 0; i < N; ++i) adj[i].clear(); | |
memset(finished,false,sizeof(finished)); | |
memset(indegree,0,sizeof(indegree)); | |
memset(dfsn,0,sizeof(dfsn)); | |
memset(sn,-1,sizeof(sn)); | |
for (int i = 0; i < M; ++i){ | |
int a, b; | |
cin >> a >> b; | |
adj[a].push_back(b); | |
} | |
for (int i = 0; i < N; ++i) | |
if(dfsn[i]==0) DFS(i); | |
for (int i = 0; i < N; ++i) | |
for (int next: adj[i]) | |
if(sn[i]!=sn[next]) indegree[sn[next]]++; | |
for (int i = 0; i < SCC.size(); ++i){ | |
if(indegree[i]==0){ | |
if(check==-1) check = i; | |
else flag = true; | |
} | |
} | |
if(flag){ | |
cout << "Confused" << '\n'; | |
} | |
else{ | |
sort(SCC[check].begin(),SCC[check].end()); | |
for (int i = 0; i < SCC[check].size(); ++i) | |
cout << SCC[check][i] << '\n'; | |
} | |
cout << '\n'; | |
} | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!