ACM MIPT - Graph existence puzzle - examples unclear - algorithm

This is with reference to the 'graph existence' problem - http://acm.mipt.ru/judge/problems.pl?problem=110. Can someone explain why there is no tree in example 1 but there is a tree in example 2? In both examples, vertices 0, 1, 2 and 3 are connected to each other. Here is the problem statement and examples for your reference:
You are given a matrix of distances in a graph.
You should check whether this graph could be a tree or set of trees (forest).
Edge length is 0 or positive integer.
Input: The first line contains number of vertices N.
Next N lines contains matrix (only left bottom triangle of matrix).
Distance -1 corresponds to infinite distance.
Output: Output YES or NO. If YES, then next lines should contains list of edges
of the tree (any tree (forest) with given distance matrix).
Each edge is coded by two identifiers of it's ends.
Vertex identifiers are numbers 0, 1, ..., N-1.
Input#1
4
0
1 0
1 1 0
1 1 1 0
Output#1
NO
Input#2
5
0
1 0
2 1 0
3 2 1 0
-1 -1 -1 -1 0
Output#2
YES
0 1
1 2
2 3

The problem is not very well translated from its Russian original.
The given matrix is not the matrix of edges in the graph as one might conclude, but a distance matrix. Each edge probably has weight of 1, but I am not entirely sure has a nonnegative weight. One has to check if the matrix can be realized by a tree or a forest.
That is in the first example all vertices are connected, but the second example can be realized the graph looks like:
Example 2:
(0) - (1) - (2) - (3) (4)
The graph in example 1 is
Example 1:
(0) - (1) - (2) - (3)
|_____|_____| |
| |___________|
|_________________|

Related

how to input this for Dijkstra algorithm question

I have an assignment on Dijkstra's algorithm, but the question has me confused about the input. It asks me to find shortest and second shortest paths, and that part I have figured out, but how do I even start with the graph has me troubled.
The question says the input has to be read from a file and the file contains the number of nodes and the weight between two nodes. Weight between two nodes should be 1 to 9, and can use 0 to indicate a path that doesn't exist.
Now my question is what has to be the contents of the file? I was able to understand Dijkstra's algorithm where the input was a 2d array that represents the graph. Can someone clarify what is expected from this question? Like what the source file should contain.
You are probably supposed to create file like this:
(example - there are many ways to do it)
4 # number of nodes (from 1 to 4)
1 2 3 # means edge from node 1 to node 2 with weight 3
2 3 1 # means edge from node 2 to node 3 with weight 1
...
this would correspond to 2d matrix like this:
0 3 0 0
0 0 1 0
0 0 0 0
0 0 0 0

Maximum path cost in matrix

Can anyone tell the algorithm for finding the maximum path cost in a NxM matrix starting from top left corner and ending with bottom right corner with left ,right , down movement is allowed in a matrix and contains negative cost. A cell can be visited any number of times and after visiting a cell its cost is replaced with 0
Constraints
1 <= nxm <= 4x10^6
INPUT
4 5
1 2 3 -1 -2
-5 -8 -1 2 -150
1 2 3 -250 100
1 1 1 1 20
OUTPUT
37
Explanation is given in the image
Explanation of Output
Since you have also negative costs then use bellman-ford. What you do is that you change sign of all the costs(convert negative signs to positive and positive to negative) then find the shortest path and this path will be the longest because you have changed the signs.
If the sign is never becoms negative then use dijkstra shrtest-path but before that make all values negative and this will return you the longest path with it's cost.
You matrix is a direct graph. In your image you are trying to find a path(max or min) from index (0,0) to (n-1,n-1).
You need these things to represent it as a graph.
You need a linkedlist and in each node you have a first_Node, second_Node,Cost to move from first node to second.
An array of linkedlist. In each array index you save a linkedlist.If for example there is a path from 0 to 5 and 0 to 1(it's an undirected graph) then your graph will look like this.
If you want a direct-graph then simply add in adj[0] = 5 and do not add in adj[5] = 0 , this means that there is path from 0 to 5 but not from 5 to zero.
Here linkedlist represents only nodes which are connected not there cost. You have to add extra variable there which keep cost for each two nodes and it will look like this.
Now instead of first linkedlist put this linkedlist in your array and you have a graph now to run shortest or longest path algorithm.
If you want an intellgent algorithm then you can use A* with heuristic, i guess manhattan will be best.
If cost of your edges is not negative then use Dijkstra.
If cost is negative then use bellman-ford algorithm.
You can always find the longest path by converting the minus sign to plus and plus to minus and then run shortest path algorithm. Path founded will be longest.
I answered this question and as you said in comments to look at point two. If that's a task then main idea of this assignment is ensure the Monotonocity.
h stands for heuristic cost.
A stands for accumulated cost.
Which says that each node the h(A) =< h(A) + A(A,B). Means if you want to move from A to B then cost should not be decreasing(can you do something with your values such that this property will hold) but increasing and once you satisfy this condition then everyone node which A* chooses , that node will be part of your path from source to Goal because this is the path with shortest/longest value.
pathMax You can enforece monotonicity. If there is path from A to B such that f(S...AB) < f(S ..B) then set cost of the f(S...AB) = Max(f(S...AB) , f(S...A)) where S means source.
Since moving up is not allowed, paths always look like a set of horizontal intervals that share at least 1 position (for the down move). Answers can be characterized as, say
struct Answer {
int layer[N][2]; // layer[i][0] and [i][1] represent interval start&end
// with 0 <= layer[i][0] <= layer[i][1] < M
// layer[0][0] = 0, layer[N][1] = M-1
// and non-empty intersection of layers i and i+1
};
An alternative encoding is to note only layer widths and offsets to each other; but you would still have to make sure that the last layer includes the exit cell.
Assuming that you have a maxLayer routine that finds the highest-scoring interval in each layer (const O(M) per layer), and that all such such layers overlap, this would yield an O(N+M) optimal answer. However, it may be necessary to expand intervals to ensure that overlap occurs; and there may be multiple highest-scoring intervals in a given layer. At this point I would model the problem as a directed graph:
each layer has one node per score-maximizing horizontal continuous interval.
nodes from one layer are connected to nodes in the next layer according to the cost of expanding both intervals to achieve at least 1 overlap. If they already overlap, the cost is 0. Edge costs will always be zero or negative (otherwise, either source or target intervals could have scored higher by growing bigger). Add the (expanded) source-node interval value to the connection cost to get an "edge weight".
You can then run Dijkstra on this graph (negate edge weights so that the "longest path" is returned) to find the optimal path. Even better, since all paths pass once and only once through each layer, you only need to keep track of the best route to each node, and only need to build nodes and edges for the layer you are working on.
Implementation details ahead
to calculate maxLayer in O(M), use Kadane's Algorithm, modified to return all maximal intervals instead of only the first. Where the linked algorithm discards an interval and starts anew, you would instead keep a copy of that contender to use later.
given the sample input, the maximal intervals would look like this:
[0]
1 2 3 -1 -2 [1 2 3]
-5 -8 -1 2 -150 => [2]
1 2 3 -250 100 [1 2 3] [100]
1 1 1 1 20 [1 1 1 1 20]
[0]
given those intervals, they would yield the following graph:
(0)
| =>0
(+6)
\ -1=>5
\
(+2)
=>7/ \ -150=>-143
/ \
(+7) (+100)
=>12 \ / =>-43
\ /
(+24)
| =>37
(0)
when two edges incide on a single node (row 1 1 1 1 20), carry forward only the highest incoming value.
For each element in a row, find the maximum cost that can be obtained if we move horizontally across the row, given that we go through that element.
Eg. For the row
1 2 3 -1 -2
The maximum cost for each element obtained if we move horizontally given that we pass through that element will be
6 6 6 5 3
Explanation:
for element 3: we can move backwards horizontally touching 1 and 2. we will not move horizontally forward as the values -1 and -2, reduces the cost value.
So the maximum cost for 3 = 1 + 2 + 3 = 6
The maximum cost matrix for each of elements in a row if we move horizontally, for the input you have given in the description will be
6 6 6 5 3
-5 -7 1 2 -148
6 6 6 -144 100
24 24 24 24 24
Since we can move vertically from one row to the below row, update the maximum cost for each element as follows:
cost[i][j] = cost[i][j] + cost[i-1][j]
So the final cost matrix will be :
6 6 6 5 3
1 -1 7 7 -145
7 5 13 -137 -45
31 29 37 -113 -21
Maximum value in the last row of the above matrix will be give you the required output i.e 37

Choose max number of non-overlapping 2x2 squares in binary bitmap

Given a rectangle consisting of 1's and 0's, how can I find the maximum number of non-overlapping 2x2 squares of 1's?
Example:
0110
1111
1111
The solution would be 2.
I know it can be solved with Bitmask DP; but I can't really grasp it - after playing with it for hours. How does it work and how can it be formalised?
I wanted to point out that the graph we get by putting vertices at the centers of squares and joining them when they overlap is not claw-free:
If we take (in the full plane) a 2x2 square and three of the four diagonally overlapping 2x2 squares, they form the induced subgraph
• •
\ /
•
/
•
This is a claw, meaning that any region containing those squares corresponds to a non-claw-free graph.
If you build a graph where every node represents a 2x2 square of 1's and there is an edge between two nodes if they overlap, then the problem is now: find the maximum independent set in this graph.
Here is a dynamic programming solution.
The state is (row number, mask of occupied cells, shift position). It looks like this:
..#..
.##..
.#...
.#...
In this case, the row number is 2(I use zero-bases indices), the mask depends on whether we take a cell with # or not, the shift position is 1. The number of states is O(n * m * 2 ^ n). The value of a state is the maximum number of picked 2x2 squares. The base case is f(1, 0, 0) = 0(it corresponds to the first row and no 2x2 squares picked so far).
The transitions are as follows:
..#.. ..#..
.00.. -> ..1..
.0... .11..
.#... .#...
This one can be used if and only if the square consists of ones in the original matrix and there were zeros in the mask(it means that we pick this square).
The other one is:
..#.. ..#..
.##.. -> ..#..
.#... .#0..
.#... .#...
This one is always applicable. It means that we do pick this 2x2 square.
When we are done with one row, we can proceed to the next one:
..#.. ..#0.
..#.. -> ..#..
..#.. ..#..
.##.. ..#..
There are at most two transitions from each state, so the total time complexity is O(n * m * 2 ^ n). The answer the maximum among all masks and shifts for the last row.
edit 20:18, there is a counterexample posted by #ILoveCoding
My intuition says, that this will work. I am unable to prove it since I'm not advanced enough. I can't think of any counterexample though.
I will try describe the solution and post the code, please correct me if my solution is wrong.
First we load input to an array.
Then we create second array of the same size and for every possible placing of 2x2 square we mark 1 in the second array. For the example posted by OP this would look like below.
0 1 0 0
1 1 1 0
0 0 0 0
Then for every 1 in second array we calculate the number of neighbours (including diagonals) + 1 (because if it doesn't have any neighbours we have to still see it as 1). We set those new numbers to the array. Now it should look like this.
0 4 0 0
3 4 3 0
0 0 0 0
Then for every non-zero value in the array we check whether it has any neighbour with bigger or equal value. If it has then move on since it can't be in the solution.
If we don't find any such value then it will be in the solution. We have to reset to zero every neighbour of the original value (because it can't be in the solution, it would overlap the solution.
So the first such number found should be 2 on the left. After processing it the array should look like following.
0 0 0 0
3 0 3 0
0 0 0 0
When we check the other 3 situation is the same.
We end up with non-zero values in the array indicating where top left corners of 2x2 squares are.
If you need the numer of them just traverse the array and count non-zero elements.
Another example
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 6 0 6 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 0 0 0 0 -> 0 0 0 0 -> 0 0 0 0
The code I write can be found here
http://ideone.com/Wq1xRo

backtracking for graph with adj list

Consider a graph with adjacency list as given below and with 4 vertices and 4 edges.
1 2 3 4
1 0 1 0 1
2 1 0 1 0
3 0 1 0 1
4 1 0 1 0
It is a simple rectangular graph.
In m-colorability graph problem we have to colour the graph with no adjacent nodes of the same color.I am reading a book which says that if the degree of the graph is 'd' then graph can be colored in d+1 ways.But the above graph can be colored in 2 ways which is the degree of the graph.How?
If graph is fully connected then the graph is colorable with d+1 color. In this case it is not fully connected so colors can be less than d+1 which is 3 here and as seen it is 2 in this case.
Note: fully connected means all vertices are connected to each other directly by edge.

Construct a graph from given node degrees

I have to find which of the following values can be the degrees of an undirected graph with 6 vertices:
a) 3 2 2 2 3 3
b) 4 2 2 2 3 2
c) 5 2 2 2 0 3
d) 5 2 2 2 1 2
I only method I found is to try to draw the graph on a sheet of paper and then check if it is possible.
I just need a hint to start this problem, if possible, in other way than drawing each graph.
The following algorithm decides if a simple graph can be constructed with given node degrees:
sort the degrees in descending order
if the first degree is 0 (i.e.all degrees are 0) then obviously such a graph can be formed (no edges) and you are done.
if the first degree has value d (> 0) then the following d degrees must be greater 0. If not you are done: no such graph can be formed.
take away the first degree (value d) and reduce the following d degrees by one (i.e. draw the requested number of edges from the node with highest degree to the nodes with highest degrees among the remaining ones - see proof below for correctness of this assumption), then continue with step 1 (with now one node less)
example a) (can be rejected because of the odd sum of weights, but also the above algorithms works)
3 2 2 2 3 3
3 3 3 2 2 2
2 2 1 2 2
2 2 2 2 1
1 1 2 1
2 1 1 1
0 0 1
1 0 0
-1 not possible
example c)
5 2 2 2 0 3
5 3 2 2 2 0
2 1 1 1 -1 not possible
example d)
5 2 2 2 1 2
5 2 2 2 2 1
1 1 1 1 0
0 1 1 0
1 1 0 0
0 0 0 ok
What is missing is a proof that if a graph can be drawn with given node degrees, then one of the matching graphs has this property of step 4, i.e. that the node with highest degree is connected with the nodes with next highest degrees.
Let us therefore assume that A is the node with highest degree and that it is connected with a node B whose degree is less then the degree of node C not being connected to A. Since degree(C) > degree(B), there is node D connected to C and not connected to B. Thus, there are edges AB and CD, and there are no edges AC nor BD. So we can replace AB and CD by the edges AC and BD without changing the nodes' degrees.
By repeating this procedure enough times we can make all nodes with the next highest degrees being connected to node with the highest degree.
The handshaking lemma or degree sum formula is necessary and sufficient condition in this case, since we only care that it forms an undirected graph (orientation of the edge doesn't matter, but nothing is said about loop or parallel edges). Therefore, option c and option d are valid 6-vertex undirected graph.
If the question asks for simple undirected graph (loop and parallel edges disallowed), then we need to bring in the algorithm by Havel/Hakimi, which is as described by #coproc.

Resources