https://www.acmicpc.net/problem/1976
Disjoint-set문제로 Union-Find 문제라고도 한다.
크루스칼에서 간선을 잇는 두 정점의 집합을 구할 때 사용되기도 하는데
Union-find가 그리디에서만 사용되지는 않기 때문에 그래프 문제로 분류를 했다.
도시를 각 정점이라고 생각했을 때
최초에 입력받는 정점의 최상위 정점을 자신의 인덱스 번호로 지정을 해주었다.
그 다음으로 연결된 두 정점이 주어졌을 때,
인덱스 번호가 작은 정점을, 인덱스 번호가 큰 정점의 부모로 Union을 해준다.
마지막으로 여행 경로를 확인한 후에
이어진 여행 경로의 두 정점(도시)의 최상위 정점을 확인하는 데, 만약 최상위 부모가 다르다면
서로 이어진 경로가 아님을 뜻하기 때문에 NO를 출력해주면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <iostream> #include <vector> using namespace std; int N,M; int map[201][201]={0}; vector<int> parent; //도시 별 최상위 도시 vector<int> path; //여행 경로 int fn_find(int node){ while(node!=parent[node]) node=parent[node]; return node; } void fn_union(int x,int y){ x=fn_find(x); y=fn_find(y); if(x<y) parent[y]=x; else parent[x]=y; } int main(){ cin>>N>>M; parent = vector<int> (N+1,0); path = vector<int> (M+1,0); for(int i=1;i<=N;i++) parent[i]=i; for(int i=1;i<=N;i++) for(int j=1;j<=N;j++){ scanf("%d",&map[i][j]); if(map[i][j]) fn_union(i,j); } for(int i=1;i<=M;i++) scanf("%d",&path[i]); bool check=true; for(int i=1;i<M;i++){ if(fn_find(path[i])!=fn_find(path[i+1])){ check=false; break; } } if(check) cout<<"YES"<<endl; else cout<<"NO"<<endl; return 0; } | cs |