summaryrefslogtreecommitdiffstats
path: root/Algorithms/Part-I/1-Percolation/PercolationJZU.java
blob: 8112b9f856359cf2f625fbff4d755da2f9dabdef (plain)
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
/* vim: set expandtab tabstop=4 shiftwidth=4 : */

public class PercolationJZU
{
    private static final int closed = -1;
    private int N;
    // faste using struct { id, weight } ?
    private int[] sites;
    private int[] weights;

    public PercolationJZU(int N)
    {
        this.N = N;
        int n = (N*N)+2;
        sites = new int[n];
        weights = new int[n];
        sites[0] = 0;
        weights[0] = N+1;
        sites[n-1] = n-1;
        weights[n-1] = N+1;
        for(int x=1; x<=n-1; x++)
        {
            sites[x] = x;
            weights[x] = closed;
        }
    }

    private int ijToX(int i, int j)
    {
        if(i<1 || j<1 || i>N || j>N)
            throw new java.lang.IndexOutOfBoundsException("check your indexes");
        return ((j-1)*N)+i;
    }

    private boolean isOpen(int x)
    {
        return (weights[x]!=closed);
    }

    private int root(int x)
    {
        while (x != sites[x])
        {
            sites[x] = sites[sites[x]];
            x = sites[x];
        }
        return x;
    }

    private void connect(int i, int j)
    {
        int ri = root(i);
        int rj = root(j);
        if (ri==rj) return;
        if (weights[ri] < weights[rj])
        {
            sites[ri] = rj;
            weights[rj] += weights[ri];
        }
        else
        {
            sites[rj] = ri;
            weights[ri] += weights[rj];
        }

    }

    public void open(int i, int j)
    {
        int x = ijToX(i,j);
        if (isOpen(x)) return;
        weights[x] = 1;
        if (i>1 && isOpen(x-1)) connect(x,x-1);
        if (i<N && isOpen(x+1)) connect(x,x+1);
        if(j==1) {
            connect(x,0);
            if (isOpen(x+N)) connect(x,x+N);
        }
        else if(j==N) {
            connect(x,N*N+1);
            if (isOpen(x-N)) connect(x,x-N);
        } else {
            if (isOpen(x-N)) connect(x,x-N);
            if (isOpen(x+N)) connect(x,x+N);
        }
    }

    public boolean isOpen(int i, int j)
    {
        return isOpen(ijToX(i,j));
    }

    public boolean isFull(int i, int j)
    {
        int x = ijToX(i,j);
        return ((isOpen(x)) && (root(x)==0));
    }

    public boolean percolates()
    {
        return (root(0)==root(N*N+1));
    }
}