Algorithm: Explanation of a graph based - algorithm

In Futaba Kindergarten, where Shinchan studies, there are N students, s_0, s_1...s_(N-1), including Shinchan. Every student knows each other directly or indirectly. Two students knows each other directly if they are friends. Indirectly knowing each other means there is a third students who knows both of them. Knowing each other is a symmetric relation, i.e., if student s_a knows student s_b then student s_b also knows student s_a.
Ai-chan is a new admission in the class. She wants to be friend with all of them. But it will be very cumbersome to befriend each of the N students there. So she decided to befriend some of them such that every student in the class is either a friend of her or friend of friend of her.
Help her to select those students such that befriending them will complete her objective. The lesser number of students the better it is.
Input
First line of input will contain two space separated integer, N M, number of students at Futaba Kindergarten, excluding Ai-chan, and number of pairs of students who are friend to each other, i.e. they knows each other directly. Then follows M lines. In each line there are two space separated integer, s_u s_v, such that student s_u and s_v are friend to each other.
Output
In first line print the total number, P, of such students. Then in next line print P space separated index of students, such that befriending them will help Ai-chan to achieve her objective.
Constraints:
1 <= N <= 10^5
1 <= M <= min(10^5, N*(N-1)/2)
0 <= s_u, s_v <= N-1
s_u != s_v
Each pair of students (s_u, s_v) knows each other, directly or indirectly.
Score: ((N-P)/N)*200
**Sample Input**
6 7
0 1
0 2
1 2
1 3
2 4
3 4
3 5
**Sample Output**
4
0 2 3 5
Im My opinion be friending with only 1 and 3 will do the job. Am i missing something ?
I am not looking for the solution , just the explanation of sample input and output.

The solution is a simple greedy algorithm. Suppose that C is the set of students.
S = {}
R = {}
while (C != {}) {
- sort the students based on their number of friends
- pick the student s with the highest number of friends
- add R = R + {s}
- add s and friends of s to the set S and remove them from C
}
print(R)

Related

Combinatorial optimization for selecting the players of a football team

I'm thinking of using integer programming to generate the optimal combination of football players to comprise a team.
Though the problem itself is simple, I'm having trouble formulating an efficient constraint for position eligibility.
I've searched stackoverflow for variants on the classic integer programming problems and came up with a temporary solution, but want to verify if the current one is efficient.
Problem
Select 11 players for a football (soccer) team from a finite set of potential players.
The team is composed of 11 slots: 5 offense, 5 defense, and 1 goal keeper.
Each role has its own respective pool of eligible players.
(e.g. goalies can only be selected from a set of players that have gloves)
Each player is assigned a 'skill score' that represents their skill
Objective function
Maximize: sum of all 11 player skill scores
Constraints
All 11 slots must be filled with at least 1 player
1 player may occupy only 1 slot
Each slot must be filled by a player that is eligible for the role
My temporary solution
Let xij: player i in consideration for slot j (j=1, 2,..., 11, 1 <= i <= n)
and w: n x 1 weight matrix representing skill score for player i
1. sum_j(xij) == 1 for each slot j
2. 0 <= sum_i(xij) <= 1 for each player i
3. 0 <= xij <= 1 if player i is eligible for slot j, == 0 otherwise
maximize sum(wTx)
I could not yet think of an elegant way to operationalize 3, so my answer for now is to hard code each cell to be 0.
I'm planning to use an integer programming library in Python (cvxpy or PuLP).
Would the current design lead to any issues in convergence or computation time?
Would there be a more efficient way to model the problem?
Notes
For simplicity, let's assume that while a player can be a candidate for multiple roles, their skill point does not change depending on role
Would the problem formulation change if the players' skill scores change depending on their synergy with other players? I'm thinking that simply expanding the x matrix by nC2 possible interactions could work, but am curious if there are better solutions.
Your IP formulation looks OK. However, this problem can also be solved using Dynamic Programming:
Let the array dp[n][mask] represent the maximum possible score you can get for placing players from 1 to n into positions that the 0 digits in the mask's binary representation correspond. For example dp[5][0b11111110101] is equal to the maximum score you can get for placing players 1 to 5 into positions 2 and 4. (second and fourth bits of the mask are zero.)
Now we recursively define dp[n][mask]:
dp[n][mask] = max{
dp[n-1][mask], # the case when we don't use player n
max_j{ dp[n-1][mask|(1<<j)] + w[n] } (1 <= j <= 11 and mask's jth bit is 0)
}
The base case is when n=0.
dp[0][mask] = {
-infinity, if there are 0 bits in mask # there are empty positions left, we want to strictly discourage this case.
0, if all 11 bits of mask is 1
}

Reducing time complexity from n^2

There are n students in a class. Soon, there's going to be an inter-school science quiz, where there'll be questions on 4 subjects, call them 1,2,3 and 4 for simplicity. There should 2 students in a team. Any student is equally likely to be good or bad at a particular subject.
We are given as input n rows, each with 4 entries in it. The student is good at i-th subject if the i-th column is equal to 1. I'm supposed to find out the total number of ways in which the school can send a team so that the two students together know all the 4 subjects.
For example,
S1: 1 1 1 1
S2: 1 1 0 1
S3: 1 0 1 1
S4: 0 0 1 1
S5: 0 0 0 0
Student 1 can go with any student since all the subjects are his strength. => 4
Student 2 can go with S3 and S4, since S2 is good in subject 1,2 and 4 and S3 and S4 are good in subject 3. => 2 (Note that (S1,S2) was already counted)
S3 will go with the one good at subject 2=> none
S4: Similarly, none.
Hence, ans=4+2=6
My solution:-
ans=0;
//arr is the array containing subject-wise "strength" of students
for(int i=0;i<n;i++){
ArrayList<Integer> a=new ArrayList<>();
for(int j=0;j<4;j++)
if(arr[i][j]==0)
a.add(j);
if(a.size()==0)
ans+=n-i-1;
else
for(int j=i+1;j<n;j++){
bool=false;
for(int k=0;k<a.size();k++){
if(arr[j][a.get(k)]==0)
break;
bool=true;
}
if(bool)
ans++;
}
}
System.out.println(ans);
Now I know my solution is correct, but its time complexity is O(n^2), and I'm looking for a better solution for the same. Thanks!
You can reduce the complexity on number of students by spending memory for the combinations of subjects.
Build a list of 2^s elements, where s is the quantity of subjects. Index the list by the combinations of subjects, interpreted as a binary number. For instance, S2 has a value of 13, and is missing a value of 2.
First tally the "needs" that each student can fill. For each combination of 1 bits in the student's known subjects, increment that index of the tally list.
for student in student_list:
score = # student's covered subjects as an int
tally = [0]*16
for idx in range(16):
if idx & score == idx:
tally[idx] += 1
You now have a list of how many students can cover each combination of needed subjects. This is O(n * 2^s)
For each student, find the needed score, the 1's complement of the student score. It is now a simple matter to add all of the tallies for the needed scores.
team_ct = 0
for student in student_list:
needed = # student's needed subjects as an int; this is 15-score (above)
team_ct += tally[needed]
Now, every pairing has been counted twice, so divide team_ct by 2.
Yes, this last bit of code can be dropped into a one-liner:
team_ct = sum([tally[15-score] for score in foo]) / 2
Where foo is a construct of all student scores. This part is O(n).

Optimization - distribute participants far from each other

This is my first question. I tried to find an answer for 2 days but I couldn't find what I was looking for.
Question: How can I minimize the amount of matches between students from the same school
I have a very practical case, I need to arrange a competition (tournament bracket)
but some of the participants might come from the same school.
Those from the same school should be put as far as possible from each other
for example: {A A A B B C} => {A B}, {A C}, {A B}
if there are more than half participants from one school, then there would be no other way but to pair up 2 guys from the same school.
for example: {A A A A B C} => {A B}, {A C}, {A A}
I don't expect to get code, just some keywords or some pseudo code on what you think would be a way of making this would be of great help!
I tried digging into constraint resolution algorithms and tournament bracket algorithms, but they don't consider minimising the amount of matches between students from same school.
Well, thank you so much in advance!
A simple algorithm (EDIT 2)
From the comments below: you have a single elimination tournament. You must choose the places of the players in the tournament bracket. If you look at your bracket, you see: players, but also pairs of players (players that play the match 1 against each other), pairs of pairs of players (winner of pair 1 against winner of pair 2 for the match 2), and so on.
The idea
Sort the students by school, the schools with the more students before the ones with the less students. e.g A B B B B C C -> B B B B C C A.
Distribute the students in two groups A and B as in a war card game: 1st student in A, 2nd student in B, 3rd student in A, 4th student in B, ...
Continue with groups A and B.
You have a recursion: the position of a player in the level k-1 (k=n-1 to 0) is ((pos at level k) % 2) * 2^k + (pos at level k) // 2 (every even goes to the left, every odd goes to the right)
Python code
Sort array by number of schools:
assert 2**math.log2(len(players)) == len(players) # n is the number of rounds
c = collections.Counter([p.school for p in players])
players_sorted_by_school_count = sorted(players, key=lambda p:-c[p.school])
Find the final position of every player:
players_sorted_for_tournament = [-1] * 2**n
for j, player in enumerate(players_sorted_by_school_count):
pos = 0
for e in range(n-1,-1,-1):
if j % 2 == 1:
pos += 2**e # to the right
j = j // 2
players_sorted_for_tournament[pos] = player
This should give groups that are diverse enough, but I'm not sure whether it's optimal or not. Waiting for comments.
First version: how to make pairs from students of different schools
Just put the students from a same school into a stack. You have as many stack as schools. Now, sort your stacks by number of students. In your first example {A A A B B C}, you get:
A
A B
A B C
Now, take the two top elements from the two first stacks. The stack sizes have changed: if needed, reorder the stacks and continue. When you have only one stack, make pairs from this stack.
The idea is to keep as many "schools-stacks" as possible as long as possible: you spare the students of small stacks until you have no choice but to take them.
Steps with your second example, {A A A A B C}:
A
A
A
A B C => output A, B
A
A
A C => output A, C
A
A => output A A
It's a matching problem (EDIT 1)
I elaborate on the comments below. You have a single elimination tournament. You must choose the places of the players in the tournament bracket. If you look at your bracket, you see: players, but also pairs of players (players that play the match 1 against each other), pairs of pairs of players (winner of pair 1 against winner of pair 2 for the match 2), and so on.
Your solution is to start with the set of all players and split it into two sets that are as diverse a possible. "Diverse" means here: the maximum number of different schools. To do so, you check all possible combinations of elements that split the set into two subsets of equals size. Then you perform recursively the same operation on those sets, until you arrive to the player level.
Another idea is to start with players and try to make pairs with other players from other school. Let's define a distance: 1 if two players are in the same school, 0 if they are in a different school. You want to make pairs with the minimum global distance.
This distance may be generalized for the pairs of players: take the number of common schools. That is: A B A B -> 2 (A & B), A B A C -> 1 (A), A B C D -> 0. You can imagine the distance between two sets (players, pairs, pairs of pairs, ...): the number of common schools. Now you can see this as a graph whose vertices are the sets (players, pairs, pairs of pairs, ...) and whose edges connect every pair of vertices with a weight that is the distance defined above. You are looking for a perfect matching (all vertices are matched) with a minimum weight.
The blossom algorithm or some of its variants seems to fit your needs, but it's probably overkill if the number of players is limited.
Create a two-dimensional array, where the first dimension will be for each school and the second dimension will be for each participant in this take-off.
Load them and you'll have everything you need linearly.
For example:
School 1 ------- Schol 2 -------- School 3
A ------------ B ------------- C
A ------------ B ------------- C
A ------------ B ------------- C
A ------------ B
A ------------ B
A
A
In the example above, we will have 3 schools (first dimension), with school 1 having 7 participants (second dimension), school 2 having 5 participants and school 3 having 3 participants.
You can also create a second array containing the resulting combinations and, for each chosen pair, delete this pair from the initial array in a loop until it is completely empty and the result array is completely full.
I think the algorithm in this answer could help.
Basically: group the students by school, and use the error tracking idea behind Bresenham's Algorithm to distribute the schools as far apart as possible. Then you pull out pairs from the list.

Rounds needed in elimination tournament

I was just wondering if anyone has a formula to evaluate the number of round in a competition in single elimination based on :
- the number of teams involved (can be >2)
- the number of qualified teams for the next round.
This is easy for 1v1 or 1v1v1v1 with 2 teams qualified per match each rounds but I am stuck for 1v1v1 with 1 or 2 qualified teams...
Thanks !
As requested, Examples :
let's start with 32 players who plays COD on 4 at a time on a "free for all" mode (each player is alone against the others).
1st round : 32 players distributed in 8 matches of 4 players
Here we want to know how many rounds it will take to go to a final match with 4 players if we choose to keep the 1 or 2 or even 3 bests players in each matches.
1st case : if we keep the 2 best of each matchs :
2nd round : 16 players distributed in 4 matches of 4 players
2nd case : if we keep only the first
2nd round : 8 players distributed in 2 matches of 4 players
(In the second case we can foresee a problem because at the next turn we will have only 2 players left which is not enough to fill a game)
The idea is to find a mathematical formula that give me the necessary number of round with the following variables :
* NumberOfPlayers : the quantity of initial participants
* NumberOfPlayersInAGame : the quantity of participants in a game
* NumberOfPlayersQualifiedInAGame : the quantity of participants qualified for the next round in after a game
Enjoy :D
For 1 winner in a k-tournament (e.g. k = 3 means 1v1v1) and N players, where N element k^x and x is a positive integer it takes g games (java code):
public int countGames(int players, int k) {
if (players <= 1) {
return 0;
} else {
players = players / k;
// the number of remaining players per round is the same as the number of games
return players + countGames(players, k);
}
}
Or mathematically:
g = sum(i from 1 to logk(N), k^(i-1)) ( logK(N) = ln(N) / ln(k) )
In a single elimination tournament each match eliminates one entrant , by definition. Therefore if there are N entrants and the tournament completes by producing M winners there must, by definition of a single elimination tournament, have been N-M matches completed. It is usually the case that M is identically 1, and therefore N-1 matches must have taken place.
Similarly each round can be analyzed, and if a match is composed of two entrants playing to determine a single winner, then a round with 2*N entrants and N survivors must have had 2*N - N = N matches. If there were 2*N + 1 entrants to the round, with one entrant having a bye, then there are N+1 survivors of the round and again 2*N+1 - (N+1) = N matches must have been played.
By working backward from the required single winner, noting the constraint that for each round each entrant plays only one game, thus eliminating only one contestant, then the maximum number of entrants supported by a single elimination tournament of K rounds is 2^k.

Flipping coins using Scala

I am trying to solve the Flipping coins problem from codechef in scala. The problem statement is as follows:
There are N coins kept on the table, numbered from 0 to N - 1.
Initally, each coin is kept tails up. You have to perform two types of
operations : 1) Flip all coins numbered between A and B. This is
represented by the command "0 A B" 2) Answer how many coins numbered
between A and B are heads up. This is represented by the command "1 A
B". Input : The first line contains two integers, N and Q. Each of the
next Q lines are either of the form "0 A B" or "1 A B" as mentioned
above.
Output : Output 1 line for each of the queries of the form "1 A B"
containing the required answer for the corresponding query.
Sample Input :
4 7
1 0 3
0 1 2
1 0 1
1 0 0
0 0 3
1 0 3
1 3 3
Sample Output :
0
1
0
2
1
Constraints : 1 <= N <= 100000 1 <= Q <= 100000 0 <= A <= B <= N - 1
In the most simplistic way, I was thinking of initializing an Array of Ints in scala as follows:
var coins = new Array[Int](1000)
If I encounter the command 0 A B, I will simply set the index of A until B+1 to 1 as follows:
for(i <- 5 until 8){
coins(i) = 1
}
If I encounter the command 1 A B, I will take a slice of the array from A until B+1 and count the number of 1's in that given slice and I will do it as follows:
val headCount = coins.slice(5,8).count(x => x == 1)
It seems like this operation take O(n) in the worst case and apparently this can be optimized to be solved in logarithmic time.
Can somebody point out what I might be doing wrong here and how can this problem be solved in the most optimal manner.
Thanks
i don't know much about scala these days, but i can suggest an answer for the more general question about O(log(n)). typically such algorithms uses trees, and i think you could do so here.
if you construct a balanced tree, with the coins as leaves, then you could store in each node the total number of coins and the number of heads in the leaves below that node. you could imagine code that flips coins working out which leaves to visit from the node information, and working in O(n) time (you still need to flip coins). but if the flipping code also updated the node data then the number of heads would be O(log(n)) because you can use the node info - you don't need to go to the leaves.
so that gives you O(n) for one command and O(log(n)) for the other.
but you can go better than that. you can make the flip operation O(log(n)) too, i think. to do this you would add to each node a "flipped" flag. if set then all the nodes below that point are flipped. there are some book-keeping details, but the general idea is there.
and if you take this to its logical conclusion, you don't actually need to store the leaves, at least at the start. you just add nodes with the level of detail required as you process the commands. at this point you basically have the interval tree mentioned in the comments.
One clean way to model this is as a BitSet, where the integer values in the set represent the indices of the heads on the board. Then you can flip the coins in a range like this:
def flip(coins: BitSet, a: Int, b: Int) = coins ^ BitSet(a to b: _*)
You can count the heads in a range similarly:
def heads(coins: BitSet, a: Int, b: Int) = (coins & BitSet(a to b: _*)).size
Or the (probably faster) mutable java.util.BitSet versions:
import java.util.BitSet
def flip(coins: BitSet, a: Int, b: Int) { coins.flip(a, b + 1) }
def heads(coins: BitSet, a: Int, b: Int) = coins.get(a, b + 1).cardinality
This isn't necessarily optimal, but it's a fairly efficient approach, since you're just flipping bits.

Resources