Repository navigation
Expand file tree
/
Copy pathJouneyToMoon.java
More file actions
192 lines (170 loc) · 5.57 KB
/
Copy pathJouneyToMoon.java
File metadata and controls
192 lines (170 loc) · 5.57 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
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
180
181
182
183
184
185
186
187
188
189
190
191
192
import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
/*
* The member states of the UN are planning to send two people to the Moon. But there is a problem. In line with their principles of global unity, they want to pair astronauts in such a way, that both are citizens of different countries.
There are N astronauts numbered with identifiers from 0 to N-1. They are qualified and trained to be sent to the moon. But the trouble is that those in charge of the mission haven’t been directly informed about the citizenship of each astronaut. The only information they have is that some particular pairs of astronauts belong to the same country.
Your task is to compute in how many ways they can pick a pair of astronauts satisfying the above criteria, to be sent to the moon. Assume that you are provided enough pairs to let you identify the groups of astronauts even though you might not know their country directly. For instance, if 1,2,3 are astronauts from the same country; it is sufficient to mention that (1,2) and (2,3) are pairs of astronauts from the same country without providing information about a third pair (1,3).
Input Format
The first line contains two integers, N and I separated by a single space. I lines follow. each line contains 2 integers separated by a single space A and B such that
0 ≤ A, B ≤ N-1
and A and B are astronauts from the same country.
Output Format
An integer containing the number of permissible ways in which a pair of astronauts can be sent to the moon.
Constraints
1<=N<=105
1<=I<=106
Sample Input
4 2
0 1
2 3
Sample Output
4
Explanation
As persons numbered 0 and 1 belong to same country and 2 and 3 belong to same country. So the UN can choose one person of 0,1 and one out of 2,3. So number of ways of choosing pair is 4.
*/
public class JouneyToMoon {
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
int[] input = new int[2];
String line = in.nextLine();
String[] result = line.split("\\s+");
for (int i = 0; i < 2; i++) {
input[i] = Integer.parseInt(result[i]);
}
int N = input[0], I = input[1];
// System.out.println("N="+N);
UF uf = new UF(N);
while (I-- > 0) {
line = in.nextLine();
result = line.split("\\s+");
for (int i = 0; i < 2; i++) {
input[i] = Integer.parseInt(result[i]);
}
// System.out.println(""+input[0]+" , "+input[1]);
uf.union(input[0], input[1]);
}
int res = N * (N - 1) / 2;
HashSet<Integer> hs;
HashMap<Integer, HashSet<Integer>> map = new HashMap<Integer, HashSet<Integer>>(
N);
for (int i = 0; i < N; i++) {
if (!map.containsKey(uf.find(i))) {
hs = new HashSet<Integer>();
map.put(uf.find(i), hs);
} else {
hs = map.get(uf.find(i));
}
hs.add(i);
}
int k;
for (HashSet<Integer> set : map.values()) {
// System.out.println(set);
k = set.size();
res -= nChoose2(k);
}
System.out.println(res);
}
static int nChoose2(int n) {
return n * (n - 1) / 2;
}
}
class UF {
private int[] id; // id[i] = parent of i
private byte[] rank; // rank[i] = rank of subtree rooted at i (cannot be
// more than 31)
private int count; // number of components
/**
* Initializes an empty union-find data structure with <tt>N</tt> isolated
* components <tt>0</tt> through <tt>N-1</tt>
*
* @throws java.lang.IllegalArgumentException
* if <tt>N < 0</tt>
* @param N
* the number of sites
*/
public UF(int N) {
if (N < 0)
throw new IllegalArgumentException();
count = N;
id = new int[N];
rank = new byte[N];
for (int i = 0; i < N; i++) {
id[i] = i;
rank[i] = 0;
}
}
/**
* Return the component identifier for the component containing site
* <tt>p</tt>.
*
* @param p
* the integer representing one object
* @return the component identifier for the component containing site
* <tt>p</tt>
* @throws java.lang.IndexOutOfBoundsException
* unless <tt>0 ≤ p < N</tt>
*/
public int find(int p) {
if (p < 0 || p >= id.length)
throw new IndexOutOfBoundsException();
while (p != id[p]) {
id[p] = id[id[p]]; // path compression by halving
p = id[p];
}
return p;
}
/**
* Return the number of components.
*
* @return the number of components (between <tt>1</tt> and <tt>N</tt>)
*/
public int count() {
return count;
}
/**
* Are the two sites <tt>p</tt> and <tt>q</tt> in the same component?
*
* @param p
* the integer representing one site
* @param q
* the integer representing the other site
* @return true if the two sites <tt>p</tt> and <tt>q</tt> are in the same
* component; false otherwise
* @throws java.lang.IndexOutOfBoundsException
* unless both <tt>0 ≤ p < N</tt> and
* <tt>0 ≤ q < N</tt>
*/
public boolean connected(int p, int q) {
return find(p) == find(q);
}
/**
* Merge the component containing site <tt>p</tt> with the the component
* containing site <tt>q</tt>.
*
* @param p
* the integer representing one site
* @param q
* the integer representing the other site
* @throws java.lang.IndexOutOfBoundsException
* unless both <tt>0 ≤ p < N</tt> and
* <tt>0 ≤ q < N</tt>
*/
public void union(int p, int q) {
int i = find(p);
int j = find(q);
if (i == j)
return;
// make root of smaller rank point to root of larger rank
if (rank[i] < rank[j])
id[i] = j;
else if (rank[i] > rank[j])
id[j] = i;
else {
id[j] = i;
rank[i]++;
}
count--;
}
}