백준 문제풀이

백준 1376 - 민식우선탐색

Vermeil 2022. 12. 15. 22:26

https://www.acmicpc.net/problem/1376

 

1376번: 민식우선탐색

첫째 줄에는 정점의 개수 N(<=100,000)과 간선의 개수 M(<=1,000,000)이 주어진다. 두 번째 줄부터 M+1번째 줄 까지는 a b의 형태로 a와 b가 간선으로 연결되어 있다는 의미의 입력이 들어온다. 모든 간선

www.acmicpc.net

[알고리즘 분류]

dfs

segment tree

 

 

 pbds로 풀어보려 했지만, clang으로도 TLE 받고 포기했다.

 

 세그먼트 트리를 사용하는 풀이는 간단한 편이다. k번째 수를 찾는 쿼리는 리프노드부터 시작하여 내려오는 과정으로 해결할 수 있다. mfs를 시행할 때마다 현재 노드 \(now\)와 연결된 노드\(nxt\)들에 대해, \(nxt\rightarrow now\) 간선들을 지워주면 된다. 간선을 지우는 것은, 세그먼트 트리에서 특정 원소를 update하는 과정으로 해결하면 된다.

 

 정답 코드는 다음과 같다.

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <bits/stdc++.h>
 
using namespace std;
 
using ll = long long;
using ld = long double;
 
typedef pair<intint> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
 
//const ld eps = 1e-9;
const ll mod = 1e9 + 7;
const ll inf = 1e9;
 
#define all(v) (v).begin(),(v).end()
#define compress(v) sort(all(v)), (v).erase(unique(all(v)), (v).end())
#define X first
#define Y second
#define endl '\n'
 
 
#define fastio ios_base::sync_with_stdio(false);cin.tie(nullptr)
#define MAX(a, b) a = (((a)<(b))?(b):(a))
#define MIN(a, b) a = (((a)>(b))?(b):(a))
 
 
// end of def
 
int n,md;
vector<int> seg[100001];
vector<int> g[100001];
 
void init(int i, int x, int s, int e){
    if (s == e) {
        seg[i][x] = 1;
        return;
    }
    int m = (s + e) / 2;
    init(i, x * 2, s, m); init(i, x * 2 + 1, m + 1, e);
    seg[i][x] = seg[i][x * 2+ seg[i][x * 2 + 1];
}
 
void upd(int i, int x, int s, int e, int idx){
    if (e < idx || idx < s) return;
    if (idx <= s && e <= idx) {
        seg[i][x] = 0;
        return;
    }
    int m = (s + e) / 2;
    upd(i, x * 2, s, m, idx); upd(i, x * 2 + 1, m + 1, e, idx);
    seg[i][x] = seg[i][x * 2+ seg[i][x * 2 + 1];
}
 
 
 
int qry(int i, int x, int s, int e, int k){
    if (s == e) return s;
    int m = (s + e) / 2;
    if (seg[i][x * 2>= k)
        return qry(i, x * 2, s, m, k);
    else
        return qry(i, x * 2 + 1, m + 1, e, k - seg[i][x * 2]);
}
 
void deleteEdge(int u, int v){
    int idx = lower_bound(all(g[u]), v) - g[u].begin();
    upd(u, 11, (int)g[u].size(), idx + 1);
}
 
void mfs(int x){
    cout<<x<<" ";
    for (int j: g[x]){
        deleteEdge(j, x);
    }
    while (seg[x][1]){
        int qr;
        if (seg[x][1& 1) qr = qry(x, 11, g[x].size(), seg[x][1/ 2 + 1);
        else qr = qry(x, 11, g[x].size(), 1);
 
        int i = g[x][qr - 1];
        mfs(i);
    }
}
 
int main() {
    fastio;
    cin>>n>>md;
    for (int i=0;i<md;i++){
        int u,v;cin>>u>>v;
        if (u == v)continue;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    for (int i=1;i<=n;i++){
        compress(g[i]);
        if (!g[i].empty()) {
            seg[i].resize(g[i].size() * 4);
            init(i, 11, g[i].size());
        }
    }
    mfs(1);
    return 0;
}
cs