GCD and Simple Path - data-structures

Given an undirected and connected graph of N vertices and N-1 edges. The number written on the ith vertex is val[i]. The task is to count the number of pairs (x, y) such that following conditions are satisfied:
0 ≤ x < y ≤ N-1
The GCD of the numbers written on the vertices on the simple path in the given graph from x to
y should be divisible by K.
Example:
Input:
N = 4, K = 2
Edges[] = {{0, 1}, {0, 2}, {2, 3}}
Val[] = {2, 6, 4, 3}
Output:
3
Explanation:
0 - 1
|
2 - 3
There are three pairs - (0,1), (1,2) and
(0,2) which satisify both the conditions.

There are two observations here:
1)It is a connected graph and it has n-1 edges. So it has to be a tree.
2)For condition 2 to be true, all the numbers written on the nodes in the simple path between x and y has to be k or a multiple of k.
With these two observations we can devise a solution
Replace all val[i]'s with val[i]%k.
Foreach i from 0 to n-1:
a. if val[i]==0, and not visited before Run a dfs from node i.
b. In dfs only visit the nodes for which val[node]=0 and not visited before. Return the number of nodes you visited on this run. Let this number be x. Also mark these nodes visited.
c. Add xC2 = (x*(x-1))/2 to the answer. (Why? because all the pairs of these visited nodes satisfies both of our conditions. We can select 2 nodes in xC2 ways.).

Related

Count ways to assign weights for a Tree so that w1 <= w2 <= ... <= wm

Question:
Given a tree with N nodes and an array of M pairs of nodes from that tree, the pairs are indexed from 1->m.
Have w[i] as the sum of weights on the path between the pair of nodes after modulo by 2. So w[i] can either be 0 or 1.
Count ways to assign weights for the Tree so that w1 <= w2 <= ... <= wm
The weights can only be 1 or 2.
Constraints:
N, M <= 30000
Example:
The graph:
The M pairs of nodes:
1 2
2 3
1 3
Answer: 2
Explaination:
Here are all the possible ways to assign edges:
Way 1:
Edge: 1 - 2 weight: 1
Edge: 1 - 3 weight: 1
w[] would be {1, 1, 0}
-> Not valid
Way 2:
Edge: 1 - 2 weight: 1
Edge: 1 - 3 weight: 2
w[] would be {1, 0, 1}
-> Not valid
Way 3:
Edge: 1 - 2 weight: 2
Edge: 1 - 3 weight: 1
w[] would be {0, 1, 1}
-> Valid
Way 4:
Edge: 1 - 2 weight: 2
Edge: 1 - 3 weight: 2
w[] would be {0, 0, 0}
-> Valid
Other valid w[] such as {0, 0, 1} or {1, 1, 1} is not counted as an answer because there are no way to assign weights to get the above arrays.
My take on O(2^N * M):
My best solution so far is to generate all possible weight assignments for the graph and check if it's valid. Which is clearly not the best way.
Is there any hint or keyword that can help me find out an optimized solution for this problem?
P/S: Sorry for my bad English, please comment if anything needs to be clarify
The relevant body of knowledge is linear algebra over the finite field
with two elements (GF(2)), and graph homology specifically.
Given edge weights, the function from a vector representing a set of
edges to the total weight of those edges in GF(2) is a linear map.
The XOR (that is, sum in GF(2)) of the tree path from A to B and the
tree path from B to C is the tree path from A to C.
Let G be the graph whose edges are the m given pairs. For each valid
w vector, we can use depth-first search in G to count the number of
valid solutions. Correctness follows from the rank–nullity theorem.
In each connected component C of G, which the depth-first search roots
at some node r, we record for each node x in C the parity of the sum of
edge weights from r to x. Whenever we find a tree arc, we can compute
the parity of the head from the parity of the tail. Whenever we find a
back arc, we can do the same, but the head already has a parity. If the
parities disagree, then there are no solutions for this particular
w.
Each tree arc corresponds to an independent equation, so by
rank–nullity, if there is any solution, then there are 2n−1−k
of them, where k is the number of tree arcs.

Count number of pairs of nodes in undirected graph such that W - L >= K

Question:
Given an undirected graph of N nodes and N-1 edges. The length of all edges are 1. Each edge i has a weight of Wi. (0 <= Wi <= 10.000)
The graph is guaranteed to not have any loops. So there's always one (and only) shortest path between 2 nodes.
Take a pair of node (u, v) from the graph:
l is the length of shortest the path between the 2 nodes
w is the edge with the largest weight in the shortest path between the 2 nodes
Given the number K, count the number of pair (u, v) from the graph such that w - l >= K
Example:
N = 3, K = 1
Edges:
1 - 2 - 3
1 - 3 - 2
(Edges are described as: u - v - w)
Answer: 6. All the possible pairs are: (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)
Brute Force Solution (N < 100):
Go over all pairs of (u, v), find the shortest path along side with w and l. Increase the answer if w - l >= K.
Time complexity: O(N^3)
P/S:
I have tried and succeeded the brute force solution (with N < 100). But I'm struggling to find a solution with N up to 100.000
To work out user202729's hint:
Find the centroid (vertex whose removal leaves subtrees that each have at most half of the vertices of the whole tree).
Count the pairs (u, v) whose path contains the centroid.
Delete the centroid and operate recursively on each of the subtrees.
Step 1 is O(n) (there's a standard algorithm) and Step 2 will be O(n log n), so the Master Theorem gives O(n log2 n) for the whole.
To implement Step 2, root the tree at the centroid and calculate, for the centroid and each of its children, the number of descendants at each depth. Put the results in Fenwick trees for O(log n)-time prefix sums.
Now, sort the edges by weight. Starting with the heaviest edge e and working our way to the lightest, we count the pairs whose path has e as its heaviest edge. The edge e connects a parent and a child; let x be the child. For each (improper, so including x) descendant u of x, let ℓ* = w − K be the greatest ℓ such that w − ℓ ≥ K. With two prefix sums, count the number of vertices v in other subtrees at depth at most ℓ* − depth(u). Then issue updates to the Fenwick trees to remove u from the count.

Graph problem for checking whether a permutation A of 1 to N number can be converted to a permutation B if we are given good pairs

I am not sure whether this is an appropriate question to post on this platform.
The problem statement is present here:
https://www.interviewbit.com/problems/permutation-swaps/
Other than that, here's a short summary of this graph-based question.
Problem statement with an example:
let N = 4
given permutation A for numbers 1 to 4,
A = [1, 3, 2, 4]
and given,
B = [1, 4, 2, 3]
other than that we are given pairs of positions,
C = [[2, 4]]
We have to find out, whether we can convert permutation A to permutation B if only numbers at pairs of positions(good pairs) mentioned in C can be swapped.
Here, in the above example for pair (2, 4) in C, the number at position 2 in A is = 3 and the number at position 4 is 4. if we, swap the numbers at both these positions, we get [1, 4, 2, 3] which is equal to B. Hence, it is possible.
Your really need to ask an actual question!
Here is a simple algorithm to strt your thinking about what you want.
Add A to L, a list of reachable permutations
Loop P over permutations in L
Loop S over C
Apply C to P, giving R
If R == B
**DONE** TRUE
If R not in L
Add R to L
**DONE** FALSE
Algorithm:
Create a graph whose nodes are the positions 1..n, and with an edge between two positions if and only if you can swap them.
For every position where you have an unwanted number, if the number you want can't be reached through the graph, then no permutation can work and you should return 0.
If every position has its wanted number reachable, then return 1.
But why is it sufficient to have every wanted number reachable?
To start, construct a maximal spanning forest in the graph according to the following pseudo-code:
foreach node in 1..10:
if node not in any tree:
construct maximal tree by breadth-first search
if tree has > 1 element:
add tree to list of trees in our forest
And now we construct our permutation as follows:
while the forest is non-empty:
pick a tree in the forest:
find a leaf in the tree:
With a chain of swaps, get the right value into that node
remove the leaf from the tree
if the tree has only 1 element left, remove the tree from the forest
I will omit the proof that this always produces a permutation that gets to the desired end result. But it does.

Number of Paths in a Graph

I have an undirected, unweighted graph. Let us fix a vertex and find all distinct paths from that vertex which covers all vertices of the graph. The task is to find the number of possible such paths from every vertices.
Eg: Let us take a graph of 4 vertices [ 1, 2, 3, 4]. And the edges are (1,2), (2,3), (3,4), (4,2). Here answer is 4. The paths are 1>2>3>4, 1>2>4>3, 3>4>2>1, 4>3>2>1.
I have come with an algorithm which uses brute-force technique to find the number of possible such paths, initialized by each vertex.Eg:
For the above example:
From vertex 1 there is 2 such path;
From vertex 2 there is no such path;
From vertex 3 there is 1 such path;
From vertex 4 there is 1 such path;
So the answer is 2+1+1=4.
Is it possible to solve this problem in a better time complexity?
There's an O(2^n n^2)-time algorithm obtained by modifying the Held--Karp DP. The idea is, for each subset S of vertices paired with some endpoint t in S, compute the number of paths that visit exactly the vertices in S and end at t by summing, for each neighbor u of t that is in S, the count for visiting S - {t} and ending at u. As a base case, the singleton sets all have count 1. In Python 3:
import itertools
def count_hamilton_paths(graph): # graph is a dict of adjacency lists
vertices = frozenset(graph)
table = {(frozenset({t}), t): 1 for t in vertices}
for r in range(2, len(vertices) + 1):
for subset_tuple in itertools.combinations(vertices, r):
subset = frozenset(subset_tuple)
for t in subset:
subset_minus_t = subset - frozenset({t})
table[(subset, t)] = sum(table[(subset_minus_t, u)]
for u in graph[t]
if u in subset_minus_t)
return sum(table[(vertices, t)] for t in vertices)
print(count_hamilton_paths({1: {2}, 2: {1, 3, 4}, 3: {2, 4}, 4: {2, 3}}))

How can I correctly draw Complete 5-Vertex Undirected Graph that satisfies Triangle Inequality

How do I, other than brute forcing, efficiently draw a correct Complete 5-Vertex Undirected Graph with distinct edge weights {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} that satisfies the Triangle inequality? I'm unaware of any algorithm that exists to generate a correct graph G for the edge weights provided.
Here's an example of a Complete 5-Vertex Graph
Here's one that works.
(2,1): 1
(3,1): 2
(3,2): 3
(4,1): 4
(4,2): 5
(4,3): 6
(5,1): 7
(5,2): 8
(5,3): 9
(5,4): 10
The generalization to an n-vertex complete graph should be clear. The proof of correctness is inductive. For n = 0, it's obvious. For higher n, the inductive hypothesis is equivalent to the proposition that every violation of the triangle inequality involves vertex n. The edges involving vertex n are longer than the others, so n is not the transit vertex of a violation. Thus every hypothetical violation (up to symmetry) looks like n -> v -> w. There exists some constant c such that n -> v has length c + v and n -> w has length c + w. Hence, if v -> w is a violation, then it has length less than w - v, which, by inspection, is impossible.

Resources