https://codeforces.com/contest/1278/problem/D
풀이가 너무 생소해서 정리해둠
<문제설명>
최대 5e5개의 정점이 입력된다. 정점은 [l,r]의 정보를 담고 있다. 서로 교차되는(intersect) 정점들이 서로 이어져있다고 할 때, 그 그래프가 트리인지 아닌지를 출력하는 문제.
ex) 정점[1,3]과 [2,4]는 이어져있다. 하지만 [1,2],[3,4]는 이어져 있지 않다.
+모든 끝점은 유일하다. 예를들어 [1,2][2,3]이 동시에 주어지는 경우는 없다
<풀이>
1. 각 정점의 정보를 P a[MAX]에 담아둔다.
2. vector<P> evs에 (a[i].first, i) 와 (a[i].second, i)를 모두 담아서 오름차순 정렬한다.
3. set<P> cand를 마련한다. (아직 교차할 정점을 찾을 여지가 남은 정점의 (끝점, 정점번호)를 기억해 두기 위함.)
4. 정렬해둔 evs를 차례로 순차하면서 ( for(P p : evs) )
4-1. cand에 p가 있는 경우 cand에서 p를 지운다.
(이제 p가 가리키는 정점은 더이상 교차할 정점을 찾을 리 없으므로)
4-2-1. cand에 p가 없는 경우 p가 시작점이든 끝점이든 일단 p가 속한 정점(u = p.second)의 시작점 끝점을 마련해둔다.
4-2-2. cand를 차례로 순차하면서, ( for(P q : cand) ) q가 속한 정점(v = q.second)의 끝점이 u의 끝점보다 작을 때에 대해서만 u와 v의 간선을 이어준다.
아래와 같은 상황은 4-1에서 해결했기 때문에 일어나지 않는다!
5. 간선을 이어줄 때 마다 cnt++ 하여 간선 수를 cnt에 기억해 둔다.
6. 첫 번째 정점부터 dfs해서 모든 정점을 방문할수 있고, cnt==n-1일 때 YES 출력한다.
<코드>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const int N = 5e5 + 10;
int n;
P a[N];
vector<int> adj[N];
bool used[N];
void dfs(int curr, int prev = -1) {
used[curr] = true;
for (int next : adj[curr]) {
if (next == prev || used[next]) continue;
dfs(next, curr);
}
}
int main() {
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i].first >> a[i].second;
vector<P> evs;
for (int i = 0; i < n; i++) {
evs.push_back({ a[i].first,i });
evs.push_back({ a[i].second,i });
}
sort(evs.begin(), evs.end());
set<P> cand;
int cnt = 0;
for (P p : evs) {
if (cand.count(p)) cand.erase(p);
else {
int u = p.second;
int lu = a[u].first, ru = a[u].second;
for (P q : cand) { //min-heap, 기준
int v = q.second;
int lv = a[v].first, rv = a[v].second;
if (rv > ru) break;
adj[u].push_back(v);
adj[v].push_back(u);
cnt++;
if (cnt >= n) break;
}
cand.insert({ ru, u });
}
}
dfs(0);
if (cnt == n - 1 && count(used, used + n, 1) == n) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
<생각>
라인스위핑은 항상 어렵다.
위 논리도 결국 n^2이다.. 트리인지검사하는것이므로 최대 n개 간선만 이어주는것이라 시간초과가 안난다.
'알고리즘 > 코드포스' 카테고리의 다른 글
Educational codeforces #69 div2 D - Yet Another Subarray Problem (dp) (0) | 2020.01.05 |
---|---|
codeforces #610 div2 B2 - K for the Price of One (구현) (0) | 2019.12.30 |
codeforces #608 div2 D - Portals (dp) (0) | 2019.12.21 |
codeforces #585 div2 B - The Number of Products (전처리, 구현) (0) | 2019.12.14 |
codeforces #604 div2 D - Beatiful Sequence (수학,발상) (0) | 2019.12.07 |