0%

圖論測資生成器

最近寫了一個 GRAPH_GEN.h 檔,想說可以方便生成測資。

簡介

  • 4~5 行是防禦性程式設計,避免多次引用標頭檔時發生編譯錯誤
  • 7~19 行用來生成隨機數
  • 21~32 行是帶有建構式的 edge 物件
  • 底下就是生成測資的物件

具體使用

  • GenTree(n) -> 生成一個有 n 個點,且無邊權的無根樹
  • GenConnectedGraph(n,m) -> 生成一個有 n 個點, m 條邊,且無邊權的連通圖
  • GenGraph(n,m) -> 生成一個有 n 個點, m 條邊,且無邊權的不保證連通圖
  • GenTree(n,k) -> 生成一個有 n 個點,且邊權介於 1~k 的無根樹
  • GenConnectedGraph(n,m,k) -> 生成一個有 n 個點, m 條邊,且邊權介於 1~k 的連通圖
  • GenGraph(n,m,k) -> 生成一個有 n 個點, m 條邊,且邊權介於 1~k 的不保證連通圖

前三個會回傳 vector<pair<int,int>> 每個皆有保證沒有自環,後三個則會回傳 vector<edge> ,以節省重複打 firstsecond 的時間

程式碼

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include<bits/stdc++.h>
using namespace std;

#ifndef GRAPH_GEN
#define GRAPH_GEN

unsigned seed=chrono::steady_clock().now().time_since_epoch().count();
mt19937_64 rng(seed);

using ll=long long;

ll Rand(ll a,ll b){
uniform_int_distribution<ll> dis(a,b);
return dis(rng);
}

ll Rand(ll a){
return Rand(1,a);
}

struct edge{
int from,to;
long long dis;

edge(){}

edge(int f,int t,long long d){
from=f;
to=t;
dis=d;
}
};

class GraphGen{
private :
struct DSU{
vector<int> dsu,rk;

DSU(int n){
dsu.resize(n+10);
rk.resize(n+10);
init();
}

void init(){
for(int i=0;i<dsu.size();++i){
dsu[i]=i;
}
}

int find(int a){
if(dsu[a]==a){
return a;
}else{
return dsu[a]=find(dsu[a]);
}
}

bool same(int a,int b){
return find(a)==find(b);
}

void uni(int a,int b){
if(same(a,b)){
return;
}

if(rk[find(a)]==rk[find(b)]){
dsu[find(b)]=find(a);
rk[a]++;
}else if(rk[find(a)]>rk[find(b)]){
dsu[find(b)]=find(a);
}else{
dsu[find(a)]=find(b);
}
}
};
public :
// nodes 1~n
static vector<pair<int,int>> GenTree(int n){
DSU dsu(n);
vector<pair<int,int>> result;

while(result.size()<n-1){
int a=Rand(n),b=Rand(n);
if(!dsu.same(a,b)){
result.emplace_back(a,b);
dsu.uni(a,b);
}
}

return result;
}
// n nodes m edges, m need to bigger than n-1
static vector<pair<int,int>> GenConnectedGraph(int n,int m){
vector<pair<int,int>> result=GenTree(n);

for(int i=0;i<m-n+1;++i){
int a,b;
do{
a=Rand(n);
b=Rand(n);
}while(a==b);

result.emplace_back(a,b);
}

return result;
}
// n nodes m edges, m need to bigger than n-1
static vector<pair<int,int>> GenGraph(int n,int m){
vector<pair<int,int>> result;

for(int i=0;i<m;++i){
int a,b;
do{
a=Rand(n);
b=Rand(n);
}while(a==b);

result.emplace_back(a,b);
}

return result;
}
// nodes 1~n, and weight in 1~k
static vector<edge> GenTree(int n,int k){
DSU dsu(n);
vector<edge> result;

while(result.size()<n-1){
int a=Rand(n),b=Rand(n),c=Rand(k);
if(!dsu.same(a,b)){
result.emplace_back(a,b,c);
dsu.uni(a,b);
}
}

return result;
}

static vector<edge> GenConnectedGraph(int n,int m,int k){
vector<edge> result=GenTree(n,k);

for(int i=0;i<m-n+1;++i){
int a,b;
do{
a=Rand(n);
b=Rand(n);
}while(a==b);

int c=Rand(k);

result.emplace_back(a,b,c);
}

return result;
}

static vector<edge> GenGraph(int n,int m,int k){
vector<edge> result;

for(int i=0;i<m;++i){
int a,b;
do{
a=Rand(n);
b=Rand(n);
}while(a==b);

int c=Rand(k);

result.emplace_back(a,b,c);
}

return result;
}
};

#endif

使用範例

1
2
3
4
5
6
7
#include<bits/stdc++.h>
#include "GRAPH_GEN.h"
using namespace std;

int main(){
vector<pair<int,int>> edges=GraphGen::GenTree(100000);
}