Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions DSU/DSU.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
class DSU{
private int n;
private int[] parentOrSize;

public DSU(int n){
this.n = n;
this.parentOrSize = new int[n];
Arrays.fill(parentOrSize,-1);
}

int merge(int a, int b){
if(!(0 <= a && a < n) || !(0 <= b && b < n)){
// この式が成立しない物は動作しません。
return -1;
}
int x = leader(a);
int y = leader(b);
if(x == y) return x;
if(-parentOrSize[x] < -parentOrSize[y]){
int tmp = x;
x = y;
y = tmp;
}
parentOrSize[x] += parentOrSize[y];
parentOrSize[y] = x;
return x;
}

boolean same(int a, int b){
if(!(0 <= a && a < n) || !(0 <= b && b < n)){
// この式が成立しない物は動作しません。
return false;
}
return leader(a) == leader(b);
}

int leader(int a){
if (parentOrSize[a] < 0){
return a;
}else{
parentOrSize[a] = leader(parentOrSize[a]);
return parentOrSize[a];
}
}

int size(int a) {
if(!(0 <= a && a < n)){
// この式が成立しない物は動作しません。
return -1;
}
return -parentOrSize[leader(a)];
}

ArrayList<ArrayList<Integer>> groups(){
int[] leaderBuf = new int[n];
int[] groupSize = new int[n];
for(int i = 0; i < n; i++){
leaderBuf[i] = leader(i);
groupSize[leaderBuf[i]]++;
}
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
for(int i = 0; i < n; i++){
result.add(new ArrayList<>());
}
for(int i = 0; i < n; i++){
result.get(leaderBuf[i]).add(i);
}
return result;
}
}
92 changes: 92 additions & 0 deletions DSU/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# クラス DSU
- - -

無向グラフに対して,

* 辺の追加
* 2 頂点が連結かの判定

を $O(α(N))$ 時間で処理することが出来ます。

また、内部的に各連結成分ごとに代表となる頂点を 11 つ持っています。辺の追加により連結成分がマージされる時、新たな代表元は元の連結成分の代表元のうちどちらかになります。

## コンストラクタ
### DSU
```java
public DSU(int n){
```

* $n$頂点$0$辺の無向グラフを作ります。

制約
頂点数 $n$ の配列 $a_0, a_1, \dots, a_{n-1}$を作ります.
初期値はすべて-1です.
(C++版だと10^8まで可能と書いてありますが、Javaだと厳しいかもしれません)
計算量: $O(n)$

## メソッド
### merge
```java
int merge(int a, int b)
```
辺$(a,b)$を足します。
$a,b$ が連結だった場合はその代表元、非連結だった場合は新たな代表元を返します。(index外の数字を入れた場合は-1を返します。)
**制約**
* 0 \leq a < n
* 0 \leq b < n

**計算量**
* ならし$O(α(n))$

### same
```java
boolean same(int a, int b){
```
頂点$a,b$が連結かどうかを返します。

**制約**
* 0 \leq a < n
* 0 \leq b < n

**計算量**
* ならし$O(α(n))$

### leader
```java
int leader(int a){
```
頂点$a$の属する連結成分の代表元を返します。

**制約**
* 0 \leq a < n

**計算量**
* ならし$O(α(n))$

### size
```java
int size(int a) {
```
頂点$a$の属する連結成分のサイズを返します。

**制約**
* 0 \leq a < n

**計算量**
* ならし$O(α(n))$

### groups
```java
ArrayList<ArrayList<Integer>> groups(){
```
グラフを連結成分に分け、その情報を返します。
返り値は「「一つの連結成分の頂点番号のリスト」のリスト」です。 (内側外側限らず)vector内でどの順番で頂点が格納されているかは未定義です。

**計算量**
* $O(n)$

## 使用例
- Java11
[[https://atcoder.jp/contests/practice2/submissions/16582269]]
- Java8
[[https://atcoder.jp/contests/practice2/submissions/16582277]]