[백준] [C++] 11400번 단절선 (dfs)
2021. 7. 22. 23:04ㆍ알고리즘/백준
1. 문제
2. 풀이
[백준] [C++] 11266번 단절점 (dfs) (tistory.com)
단절점 문제와 유사하다.
dfs 스패닝 트리에서 부모 노드 - 자손 노드 의 간선을 조사할때
자손이 루트인 서브트리에서 부모로 가는 간선을 제외한 역방향 간선을 조사.
만약 서브트리에서 역방향간선이 전부 부모노드를 거슬러 올라가지 못할 경우.
부모노드 -> 자손 노드 의 간선이 단절선이되어
이 선을 제거하면 컴포넌트가 분리된다.
부모 노드로 가는 간선을 제외해야하는 이유 = 자손 노드의 자손들이 이 부모노드와 연결될경우, 현재 부모 - 자손 노드의 간선은 단절선이 될 수 없음. = 만약 부모노드로 가는 간선을 무시안할 경우 최소는 항상 부모노드와 같거나 작은값을 가지게됨 = 따라서 단절선을 제대로 파악할 수 없게됨 |
3. 코드
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int V, E;
vector<vector<int> > adjList;
set<pair<int, int> > answer;
int dfs(int here, int parent, vector<int>& discovered, int& visitedNum) {
int ret = discovered[here] = visitedNum++;
for(int i = 0; i < adjList[here].size(); i++) {
int there = adjList[here][i];
int subTree = discovered[there];
if(parent == there) continue;
if(subTree == -1) {
subTree = dfs(there, here, discovered, visitedNum);
if(subTree > discovered[here]) {
int a = here, b = there;
if(a > b) {
swap(a, b);
}
answer.insert({a, b});
}
}
ret = min(ret, subTree);
}
return ret;
}
void dfsAll() {
vector<int> discovered(V + 1, -1);
int visitedNum = 0;
for(int i = 0; i < V; i++) {
if(discovered[i+1] == -1) {
dfs(i+1, 0, discovered, visitedNum);
}
}
cout<<answer.size()<<"\n";
for(auto item : answer) {
cout<<item.first<< " "<<item.second<<"\n";
}
}
//a < b
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>V>>E;
adjList = vector<vector<int> > (V + 1);
for(int i = 0; i < E; i++) {
int a, b;
cin>>a>>b;
adjList[a].push_back(b);
adjList[b].push_back(a);
}
dfsAll();
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] [C++] 1533번 길의 개수 (그래프 변환, 행렬 제곱) (0) | 2021.09.18 |
---|---|
[백준][C++] 4206번 피보나치 단어 (dp, kmp) (0) | 2021.08.30 |
[백준] [C++] 11266번 단절점 (dfs) (0) | 2021.07.21 |
[백준] [C++] 1761번 정점들의 거리 (LCA, segment tree) (0) | 2021.07.20 |
[백준] [C++] 1708번 볼록 껍질 (geometry) (0) | 2021.07.19 |