forked from Sanat-2508/CS648-mini-project-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEfficient_simuation.cpp
More file actions
124 lines (103 loc) · 3.09 KB
/
Efficient_simuation.cpp
File metadata and controls
124 lines (103 loc) · 3.09 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "bits/stdc++.h"
using namespace std;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
using ll = long long;
struct dsu {
public:
dsu() : _n(0) {}
explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}
int merge(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
return x;
}
bool same(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
return leader(a) == leader(b);
}
int leader(int a) {
assert(0 <= a && a < _n);
if (parent_or_size[a] < 0) return a;
return parent_or_size[a] = leader(parent_or_size[a]);
}
int size(int a) {
assert(0 <= a && a < _n);
return -parent_or_size[leader(a)];
}
std::vector<std::vector<int>> groups() {
std::vector<int> leader_buf(_n), group_size(_n);
for (int i = 0; i < _n; i++) {
leader_buf[i] = leader(i);
group_size[leader_buf[i]]++;
}
std::vector<std::vector<int>> result(_n);
for (int i = 0; i < _n; i++) {
result[i].reserve(group_size[i]);
}
for (int i = 0; i < _n; i++) {
result[leader_buf[i]].push_back(i);
}
result.erase(
std::remove_if(result.begin(), result.end(),
[&](const std::vector<int>& v) { return v.empty(); }),
result.end());
return result;
}
private:
int _n;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
};
ll generateDiscreteRandom(ll min, ll max) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<ll> dis(min, max);
return dis(gen);
}
double generateUniformRandom(double low, double high) {
// Create a random device to seed the generator
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(low, high);
return dis(gen);
}
double Sample_lowest(ll RV_cnt , double low){
double U = generateUniformRandom(0, 1);
return 1 - (1-low)*pow((1 - U), 1/double(RV_cnt));
}
ll hashs(ll a, ll b){
return (ll(1e9)*a + b);
}
signed main(){
ll n; cin>>n;
unordered_set<ll> st;
dsu d(n);
double ans = 0;
ll edge_cnt = 0;
ll i = 0;
double curr = 0;
for(i = 0; ; i++){
if(edge_cnt == n-1) break;
ll a = generateDiscreteRandom(0, n-1), b = generateDiscreteRandom(0, n-1);
if(a==b) continue;
if(a>b) swap(a, b);
if(st.count(hashs(a, b))) continue;
st.insert(hashs(a, b));
curr = Sample_lowest((n*(n-1))/2 - i , curr);
if(!d.same(a, b)){
d.merge(a, b);
ans += curr;
edge_cnt++;
}
}
cout<<ans<<'\n';
cerr<<"Time:"<<1000*((double)clock())/(double)CLOCKS_PER_SEC<<"ms\n";
return 0;
}